diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a84dc763..fee343308 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,11 +23,27 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest pytest-cov pytest-shell + python setup.py install + - name: Install Python Poetry + run: | + python -m pip install --upgrade pip + pip install poetry + poetry install --with dev + - name: test if api works + run: poetry run python examples/api/jigen_dann_transformer.py - name: Generate coverage report - run: pytest --cov=domainlab tests/ --cov-report=xml + run: rm -r zoutput && poetry run pytest --cov=domainlab tests/ --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 with: flags: unittests env_vars: OS,PYTHON fail_ci_if_error: true + env: + CODECOV_TOKEN: 02ecb3ac-b7ce-4ea4-90a2-961c3d1a1030 + - name: check if readme yaml works + run: rm -r zoutput && python main_out.py -c ./examples/conf/vlcs_diva_mldg_dial.yaml + - name: test if examples in markdown works + run: bash -x -v ci_run_examples.sh + - name: test if benchmark works + run: pip install snakemake==7.32.0 && pip install pulp==2.7.0 && sed -i '1s/^/#!\/bin\/bash -x -v\n/' run_benchmark_standalone.sh && bash -x -v run_benchmark_standalone.sh examples/benchmark/demo_shared_hyper_grid.yaml && cat zoutput/benchmarks/mnist_benchmark_grid/hyperparameters.csv && cat zoutput/benchmarks/mnist_benchmark_grid/results.csv diff --git a/.gitignore b/.gitignore index 4aaafb41b..edfe19c37 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ tests/__pycache__/ *.pyc .vscode/ -.snakemake/ +data/pacs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..9b66a6665 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 # Use the specific version of the repo + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - repo: https://github.com/pycqa/flake8 + rev: 7.0.0 + hooks: + - id: flake8 + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort + - repo: https://github.com/psf/black + rev: 23.12.1 + hooks: + - id: black diff --git a/MANIFEST.IN b/MANIFEST.IN new file mode 100644 index 000000000..7772e7c92 --- /dev/null +++ b/MANIFEST.IN @@ -0,0 +1,2 @@ +# include data +recursive-include zdata * diff --git a/README.md b/README.md index 392512bb2..4f1f513e9 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,103 @@ -# DomainLab: Playground for Domain Generalization +# DomainLab: modular python package for training domain invariant neural networks -![GH Actions CI ](https://github.com/marrlab/DomainLab/actions/workflows/ci.yml/badge.svg) +![GH Actions CI ](https://github.com/marrlab/DomainLab/actions/workflows/ci.yml/badge.svg?branch=master) [![codecov](https://codecov.io/gh/marrlab/DomainLab/branch/master/graph/badge.svg)](https://app.codecov.io/gh/marrlab/DomainLab) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/bc22a1f9afb742efb02b87284e04dc86)](https://www.codacy.com/gh/marrlab/DomainLab/dashboard) +[![Documentation](https://img.shields.io/badge/Documentation-Here)](https://marrlab.github.io/DomainLab/) +[![pages-build-deployment](https://github.com/marrlab/DomainLab/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/marrlab/DomainLab/actions/workflows/pages/pages-build-deployment) -## Domain Generalization and DomainLab +## Distribution shifts, domain generalization and DomainLab -Domain Generalization aims at learning domain invariant features by utilizing data from multiple domains so the learned feature can generalize to new unseen domains. +Neural networks trained using data from a specific distribution (domain) usually fails to generalize to novel distributions (domains). Domain generalization aims at learning domain invariant features by utilizing data from multiple domains (data sites, corhorts, batches, vendors) so the learned feature can generalize to new unseen domains (distributions). -## Why a dedicated package +DomainLab is a software platform with state-of-the-art domain generalization algorithms implemented, designed by maximal decoupling of different software components thus enhances maximal code reuse. -Domain generalization algorithm try to learn domain invariant features by adding regularization upon the ERM (Emperical Risk Minimization) loss. A typical setting of evaluating domain generalization algorithm is the so called leave-one-domain-out scheme, where one dataset is collected from each distribution. Each time, one dataset/domain is left as test-set to estimate the generalization performance of a model trained upon the rest of domains/datasets. +### DomainLab +DomainLab decouples the following concepts or objects: +- task $M$: In DomainLab, a task is a container for datasets from different domains. (e.g. from distribution $D_1$ and $D_2$). Task offer a static protocol to evaluate the generalization performance of a neural network: which dataset(s) is used for training, wich dataset(s) used for testing. +- neural network: a map $\phi$ from the input data to the feature space and a map $\varphi$ from feature space to output $\hat{y}$ (e.g. decision variable). +- model: structural risk in the form of $\ell() + \mu R()$ where + - $\ell(Y, \hat{y}=\varphi(\phi(X)))$ is the task specific empirical loss (e.g. cross entropy for classification task). + - $R(\phi(X))$ is the penalty loss to boost domain invariant feature extraction using $\phi$. + - $\mu$ is the corresponding multiplier to each penalty function factor. +- trainer: an object that guides the data flow to model and append further domain invariant losses +like inter-domain feature alignment. +We offer detailed documentation on how these models and trainers work in our documentation page: https://marrlab.github.io/DomainLab/ -Once you came across a claim, that a domain generalization algorithm A can generate a "better" model h upon some datasets D with "better" performance compared to other algorithms, have you ever wondered: +DomainLab makes it possible to combine models with models, trainers with models, and trainers with trainers in a decorator pattern like line of code `Trainer A(Trainer B(Model C(Model D(network E), network E, network F)))` which correspond to $\ell() + \mu_a R_a() + \mu_b R_b + \mu_c R_c() + \mu_d R_d()$, where Model C and Model D share neural network E, but Model C has an extra neural network F. All models share the same neural network for feature extraction, but can have different auxilliary networks for $R()$. -- Is this mostly attributed to a more "powerful" neural network architecture of model A compared to others? What will happen if I change the backbone neural network of algorithm A from ResNet to AlexNet? -- Is this mostly attributed the protocol of estimating the generalization performance? e.g. dataset split, Will this algorithm "work" for my datasets? -- Is this mostly attributed to the "clever" regularization algorithm or a special loss function A has used for the neural network? +
+
+ +
+
-To maximally decouple these attributing factors, DomainLab was implemented with software design patterns, where - -- Domain generalization algorithms was implemented in a way that keeps the underlying neural network architecture transparent, i.e. the concrete neural network architecture can be replaced like a plugin through specifying a custom neural network architecture implemented in a python file. See [Specify Custom Neural Networks for an algorithm](./docs/doc_custom_nn.md) +## Getting started -- To evaluate a domain generalization algorithm's performance, the user can specify a "Task" in the form of custom python file and feed into the command line argument, thus it is at the user's discretion on how to evaluate an algorithm, so that all domain generalization algorithms could be compared fairly. See [Task Specification](./docs/doc_tasks.md). +### Installation +For development version in Github, see [Installation and Dependencies handling](./docs/doc_install.md) -- To simply test an algorithm's performance, there is no need to change any code inside this repository, the user only need to extend this repository to fit their custom need. +We also offer a PyPI version here https://pypi.org/project/domainlab/ which one could install via `pip install domainlab` and it is recommended to create a virtual environment for it. -## Getting started -### Installation +### Task specification +We offer various ways for the user to specify a scenario to evaluate the generalization performance via training on a limited number of datasets. See detail in +[Task Specification](./docs/doc_tasks.md) -- Install via python-poetry: -Read the python-poetry documentation https://python-poetry.org/ and use the configuration file in this repository. +### Example and usage -- **Or** only install dependencies via pip -Suppose you have cloned the repository and have changed directory to the cloned repository. +#### Either clone this repo and use command line -```bash -pip install -r requirements.txt +`python main_out.py -c ./examples/conf/vlcs_diva_mldg_dial.yaml` +where the configuration file below can be downloaded [here](https://raw.githubusercontent.com/marrlab/DomainLab/master/examples/conf/vlcs_diva_mldg_dial.yaml) ``` +te_d: caltech # domain name of test domain +tpath: examples/tasks/task_vlcs.py # python file path to specify the task +bs: 2 # batch size +model: dann_diva # combine model DANN with DIVA +epos: 1 # number of epochs +trainer: mldg_dial # combine trainer MLDG and DIAL +gamma_y: 700000.0 # hyperparameter of diva +gamma_d: 100000.0 # hyperparameter of diva +npath: examples/nets/resnet.py # neural network for class classification +npath_dom: examples/nets/resnet.py # neural network for domain classification +``` +See details in [Command line usage](./docs/doc_usage_cmd.md) -### Basic usage -Suppose you have cloned the repository and the dependencies ready, change directory to the repository: -DomainLab comes with some minimal toy-dataset to test its basis functionality. To train a domain generalization model with a user-specified task, one can execute a command similar to the following. +#### or Programm against DomainLab API -```bash -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --aname=diva --gamma_y=7e5 --gamma_d=1e5 --nname=alexnet --nname_dom=conv_bn_pool_2 -``` +See example here: [Transformer as feature extractor, decorate JIGEN with DANN, training using MLDG decorated by DIAL](https://github.com/marrlab/DomainLab/blob/master/examples/api/jigen_dann_transformer.py) -where `--tpath` specifies the path of a user specified python file which defines the domain generalization task, see Example in [Task Specification](./docs/doc_tasks.md). `--aname` specifies which algorithm to use, see [Available Algorithms](./docs/doc_algos.md), `--bs` specifies the batch size, `--debug` restrain only running for 2 epochs and save results with prefix 'debug'. For DIVA, the hyper-parameters include `--gamma_y=7e5` which is the relative weight of ERM loss compared to ELBO loss, and `--gamma_d=1e5`, which is the relative weight of domain classification loss compared to ELBO loss. -`--nname` is to specify which neural network to use for feature extraction for classification, `--nname_dom` is to specify which neural network to use for feature extraction of domains. -For usage of other arguments, check with -```bash -python main_out.py --help -``` +### Benchmark different methods +DomainLab provides a powerful benchmark functionality. +To benchmark several algorithms(combination of neural networks, models, trainers and associated hyperparameters), a single line command along with a benchmark configuration files is sufficient. See details in [benchmarks documentation and tutorial](./docs/doc_benchmark.md) -See also [Examples](./docs/doc_examples.md). +One could simply run +`bash run_benchmark_slurm.sh your_benchmark_configuration.yaml` to launch different experiments with specified configuraiton. -### Output structure (results storage) and Performance Measure -[Output structure and Performance Measure](./docs/doc_output.md) -## Custom Usage +For example, the following result (without any augmentation like flip) is for PACS dataset using ResNet. -### Define your task -Do you have your own data that comes from different domains? Create a task for your data and benchmark different domain generlization algorithms according to the following example. See -[Task Specification](./docs/doc_tasks.md) +
+
+ +
+
Benchmark results plot generated from DomainLab, where each rectangle represent one model trainer combination, each bar inside the rectangle represent a unique hyperparameter index associated with that method combination, each dot represent a random seeds.
+
+
+
-### Custom Neural network -This library decouples the concept of algorithm (model) and neural network architecture where the user could plugin different neural network architectures for the same algorithm. See -[Specify Custom Neural Networks for an algorithm](./docs/doc_custom_nn.md) -## Software Design Pattern, Extend or Contribution, Credits -[Extend or Contibute](./docs/doc_extend_contribute.md) +### Temporary citation + +```bibtex +@manual{domainlab, + title={{DomainLab: modular python package for training domain invariant neural networks}}, + author={{Xudong Sun, et.al.}}, + organization={{Institute of AI for Health}}, + year={2023}, + url={https://github.com/marrlab/DomainLab}, + note={temporary citation for domainlab} +} +``` diff --git a/ci.sh b/ci.sh index 78a5fd023..408dc2d95 100644 --- a/ci.sh +++ b/ci.sh @@ -1,12 +1,23 @@ #!/bin/bash -x -v set -e # exit upon first error starttime=`date +%s` + +# run examples bash -x -v ci_run_examples.sh + +# run test sh ci_pytest_cov.sh + +# run benchmark +./run_benchmark_standalone.sh examples/benchmark/demo_benchmark.yaml + +# update documentation +# if git status | grep -q 'master'; then + # echo "in master branch" sh gen_doc.sh +# fi + endtime=`date +%s` runtime=$((endtime-starttime)) echo "total time used:" echo "$runtime" - - diff --git a/ci_benchmark.sh b/ci_benchmark.sh new file mode 100644 index 000000000..e56700796 --- /dev/null +++ b/ci_benchmark.sh @@ -0,0 +1,3 @@ +sed -n '/```shell/,/```/ p' docs/doc_benchmark.md | sed '/^```/ d' > ./sh_temp_benchmark.sh +bash -x -v -e sh_temp_benchmark.sh +echo "benchmark done" diff --git a/ci_pytest_cov.sh b/ci_pytest_cov.sh index 8c54c4502..c0ebf6d70 100644 --- a/ci_pytest_cov.sh +++ b/ci_pytest_cov.sh @@ -1,3 +1,6 @@ #!/bin/bash -# export CUDA_VISIBLE_DEVICES="" -python -m pytest --cov=domainlab +export CUDA_VISIBLE_DEVICES="" +# although garbage collector has been explicitly called, sometimes there is still CUDA out of memory error +# so it is better not to use GPU to do the pytest to ensure every time there is no CUDA out of memory error occuring +# --cov-report term-missing to show in console file wise coverage and lines missing +python -m pytest --cov=domainlab --cov-report html diff --git a/ci_run_examples.sh b/ci_run_examples.sh index 90a3f8c58..9f6b4e041 100644 --- a/ci_run_examples.sh +++ b/ci_run_examples.sh @@ -1,4 +1,37 @@ #!/bin/bash -x -v set -e # exit upon first error -sed 's/`//g' docs/doc_examples.md > ./sh_temp.sh -bash -x -v -e sh_temp.sh +# >> append content +# > erase original content + +# echo "#!/bin/bash -x -v" > sh_temp_example.sh +sed -n '/```shell/,/```/ p' docs/doc_examples.md | sed '/^```/ d' >> ./sh_temp_example.sh +split -l 5 sh_temp_example.sh sh_example_split +for file in sh_example_split*; +do (echo "#!/bin/bash -x -v" > "$file"_exe && cat "$file" >> "$file"_exe && bash -x -v "$file"_exe && rm -r zoutput); +done +# bash -x -v -e sh_temp_example.sh +echo "general examples done" + +echo "#!/bin/bash -x -v" > sh_temp_mnist.sh +sed -n '/```shell/,/```/ p' docs/doc_MNIST_classification.md | sed '/^```/ d' >> ./sh_temp_mnist.sh +bash -x -v -e sh_temp_mnist.sh +echo "mnist example done" + +echo "#!/bin/bash -x -v" > sh_temp_nn.sh +sed -n '/```shell/,/```/ p' docs/doc_custom_nn.md | sed '/^```/ d' >> ./sh_temp_nn.sh +bash -x -v -e sh_temp_nn.sh +echo "arbitrary nn done" + +echo "#!/bin/bash -x -v" > sh_temp_task.sh +sed -n '/```shell/,/```/ p' docs/doc_tasks.md | sed '/^```/ d' >> ./sh_temp_task.sh +bash -x -v -e sh_temp_task.sh +echo "task done" + +echo "#!/bin/bash -x -v" > sh_temp_readme.sh +sed -n '/```shell/,/```/ p' README.md | sed '/^```/ d' >> ./sh_temp_readme.sh +bash -x -v -e sh_temp_readme.sh +echo "read me done" + +echo "#!/bin/bash -x -v" > sh_temp_extend.sh +sed -n '/```shell/,/```/ p' docs/doc_extend_contribute.md | sed '/^```/ d' >> ./sh_temp_extend.sh +bash -x -v -e sh_temp_extend.sh diff --git a/data/mixed_codec/caltech/auto/text.txt b/data/mixed_codec/caltech/auto/text.txt index 5e1c309da..557db03de 100644 --- a/data/mixed_codec/caltech/auto/text.txt +++ b/data/mixed_codec/caltech/auto/text.txt @@ -1 +1 @@ -Hello World \ No newline at end of file +Hello World diff --git a/data/pacs_split/readme.txt b/data/pacs_split/readme.txt index 316563bde..36a00efc7 100644 --- a/data/pacs_split/readme.txt +++ b/data/pacs_split/readme.txt @@ -1,3 +1,10 @@ 1. The h5py files was pre-read using cv2, so it is BGR channel order. -2. This benckmark is sensitive to the different train val splits, so please use this train val splits for the fair comparisons. \ No newline at end of file +2. This benckmark is sensitive to the different train val splits, so please use this train val splits for the fair comparisons. + +https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd + +[https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd](https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd) + + +https://github.com/facebookresearch/DomainBed/blob/4294ec699df761b46a1505734f6be16ef009cad9/domainbed/scripts/download.py#L29 diff --git a/data/script/download_pacs.py b/data/script/download_pacs.py new file mode 100644 index 000000000..51c346f24 --- /dev/null +++ b/data/script/download_pacs.py @@ -0,0 +1,64 @@ +"this script can be used to download the pacs dataset" +import os +import tarfile +from zipfile import ZipFile + +import gdown + + +def stage_path(data_dir, name): + """ + creates the path to data_dir/name + if it does not exist already + """ + full_path = os.path.join(data_dir, name) + + if not os.path.exists(full_path): + os.makedirs(full_path) + + return full_path + + +def download_and_extract(url, dst, remove=True): + """ + downloads and extracts the data behind the url + and saves it at dst + """ + gdown.download(url, dst, quiet=False) + + if dst.endswith(".tar.gz"): + with open(dst, "r:gz") as tar: + tar.extractall(os.path.dirname(dst)) + tar.close() + + if dst.endswith(".tar"): + with open(dst, "r:") as tar: + tar.extractall(os.path.dirname(dst)) + tar.close() + + if dst.endswith(".zip"): + zfile = ZipFile(dst, "r") + zfile.extractall(os.path.dirname(dst)) + zfile.close() + + if remove: + os.remove(dst) + + +def download_pacs(data_dir): + """ + download and extract dataset pacs. + Dataset is saved at location data_dir + """ + full_path = stage_path(data_dir, "PACS") + + download_and_extract( + "https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd", + os.path.join(data_dir, "PACS.zip"), + ) + + os.rename(os.path.join(data_dir, "kfold"), full_path) + + +if __name__ == "__main__": + download_pacs("../pacs") diff --git a/data/ztest_files/aggret_res_test1 b/data/ztest_files/aggret_res_test1 index 655faef0e..f53acf3ae 100644 --- a/data/ztest_files/aggret_res_test1 +++ b/data/ztest_files/aggret_res_test1 @@ -1,7 +1,2 @@ -param_index, task, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc 0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 -0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 -0, Task2, hduva, 2, caltech, 1, "{'a': 1, 'b': 3}", 0.76, 0.76, 0.49, 0.56, 0.57, 0.76 -0, Task2, hduva, 2, caltech, 2, "{'a': 1, 'b': 3}", 0.76, 0.76, 0.49, 0.56, 0.57, 0.76 -0, Task3, deepall, 2, caltech, 1, "{}", 0.7, 0.65, 0.5, 0.5, 0.5, 0.7 -0, Task3, deepall, 2, caltech, 2, "{}", 0.7, 0.65, 0.5, 0.5, 0.5, 0.7 diff --git a/data/ztest_files/aggret_res_test11 b/data/ztest_files/aggret_res_test11 index 23651567d..797cc5055 100644 --- a/data/ztest_files/aggret_res_test11 +++ b/data/ztest_files/aggret_res_test11 @@ -1,4 +1,4 @@ -param_index, task, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc 0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.8111111, 0.8232258, 0.6903785, 0.6903785, 0.71645665, 0.89284086 1, Task1, diva, 2, caltech, 1, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8095455 diff --git a/data/ztest_files/aggret_res_test2 b/data/ztest_files/aggret_res_test2 index c5f0571fb..93104ef85 100644 --- a/data/ztest_files/aggret_res_test2 +++ b/data/ztest_files/aggret_res_test2 @@ -1,23 +1,5 @@ -param_index, task, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc 0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.8111111, 0.8232258, 0.6903785, 0.6903785, 0.71645665, 0.89284086 2, Task1, diva, 2, caltech, 3, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.77397263, 0.82765615, 0.59528303, 0.59528303, 0.5953641, 0.74150944 -2, Task1, diva, 2, caltech, 4, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.851917, 0.7569983, 0.8873113, 0.8173113, 0.7985473, 0.8769811 -2, Task1, diva, 2, caltech, 5, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.84, 0.85, 0.615, 0.62, 0.62, 0.74 -1, Task1, diva, 2, caltech, 1, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8095455 -1, Task1, diva, 2, caltech, 2, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.82222223, 0.8609804, 0.6981304, 0.6981304, 0.7278397, 0.9361605 -1, Task1, diva, 2, caltech, 3, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.85397263, 0.95765615, 0.67528303, 0.6728303, 0.6853641, 0.81150944 -1, Task1, diva, 2, caltech, 4, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.971917, 0.8869983, 0.9273113, 0.9273113, 0.8285473, 0.9369811 -1, Task1, diva, 2, caltech, 5, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.92, 0.91, 0.74, 0.75, 0.67, 0.8 -0, Task2, hduva, 2, caltech, 1, "{'gamma_y': 97228, 'zy_dim': 76}", 0.76, 0.76, 0.49, 0.56, 0.57, 0.76 -0, Task2, hduva, 2, caltech, 2, "{'gamma_y': 97228, 'zy_dim': 76}", 0.81, 0.75, 0.45, 0.64, 0.75, 0.89 -0, Task2, hduva, 2, caltech, 3, "{'gamma_y': 97228, 'zy_dim': 76}", 0.8251667, 0.104563385, 0.10817383, 0.90109926, 0.08242064, 0.519054 -0, Task2, hduva, 2, caltech, 4, "{'gamma_y': 97228, 'zy_dim': 76}", 0.97535366, 0.88569593, 0.87402904, 0.98618114, 0.87845683, 0.99118155 -0, Task2, hduva, 2, caltech, 5, "{'gamma_y': 97228, 'zy_dim': 76}", 0.82422227, 0.10658247, 0.1084048, 0.9009563, 0.08635866, 0.51927835 -1, Task2, hduva, 2, caltech, 1, "{'gamma_y': 196616, 'zy_dim': 68}", 0.75, 0.81, 0.45, 0.54, 0.39, 0.88 -1, Task2, hduva, 2, caltech, 2, "{'gamma_y': 196616, 'zy_dim': 68}", 0.73, 0.72, 0.51, 0.51, 0.6, 0.88 -1, Task2, hduva, 2, caltech, 1, "{'gamma_y': 113475, 'zy_dim': 48}", 0.8551667, 0.204563385, 0.20817383, 0.80109926, 0.15242064, 0.559054 -1, Task2, hduva, 2, caltech, 2, "{'gamma_y': 113475, 'zy_dim': 48}", 0.57535366, 0.52569593, 0.41402904, 0.68618114, 0.57845683, 0.89118155 -1, Task2, hduva, 2, caltech, 3, "{'gamma_y': 113475, 'zy_dim': 48}", 0.72422227, 0.20658247, 0.2084048, 0.7009563, 0.18635866, 0.61927835 -1, Task2, deepall, 2, caltech, 1, "{}", 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 -1, Task2, deepall, 2, caltech, 2, "{}", 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 +0, Task2, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 diff --git a/data/ztest_files/aggret_res_test21 b/data/ztest_files/aggret_res_test21 index c5f0571fb..5bb677ba7 100644 --- a/data/ztest_files/aggret_res_test21 +++ b/data/ztest_files/aggret_res_test21 @@ -1,4 +1,4 @@ -param_index, task, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc 0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.8111111, 0.8232258, 0.6903785, 0.6903785, 0.71645665, 0.89284086 2, Task1, diva, 2, caltech, 3, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.77397263, 0.82765615, 0.59528303, 0.59528303, 0.5953641, 0.74150944 @@ -19,5 +19,5 @@ param_index, task, algo, epos, te_d, seed, params, acc, precision, recall, speci 1, Task2, hduva, 2, caltech, 1, "{'gamma_y': 113475, 'zy_dim': 48}", 0.8551667, 0.204563385, 0.20817383, 0.80109926, 0.15242064, 0.559054 1, Task2, hduva, 2, caltech, 2, "{'gamma_y': 113475, 'zy_dim': 48}", 0.57535366, 0.52569593, 0.41402904, 0.68618114, 0.57845683, 0.89118155 1, Task2, hduva, 2, caltech, 3, "{'gamma_y': 113475, 'zy_dim': 48}", 0.72422227, 0.20658247, 0.2084048, 0.7009563, 0.18635866, 0.61927835 -1, Task2, deepall, 2, caltech, 1, "{}", 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 -1, Task2, deepall, 2, caltech, 2, "{}", 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 +1, Task2, erm, 2, caltech, 1, "{}", 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 +1, Task2, erm, 2, caltech, 2, "{}", 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 diff --git a/data/ztest_files/dummy_file.py b/data/ztest_files/dummy_file.py new file mode 100644 index 000000000..e0c7faa27 --- /dev/null +++ b/data/ztest_files/dummy_file.py @@ -0,0 +1,4 @@ +""" +I am a dummy file used in tests/test_git_tag.py +to produce a file which is not commited +""" diff --git a/data/ztest_files/test_parameter_samples.csv b/data/ztest_files/test_parameter_samples.csv index 916991269..e3ebdbf4a 100644 --- a/data/ztest_files/test_parameter_samples.csv +++ b/data/ztest_files/test_parameter_samples.csv @@ -1,2 +1,2 @@ -,task,algo,params -0,Task_diva,diva,"{'gamma_y': 10e5, 'gamma_d': 1e5}" \ No newline at end of file +,method,model,params +0,diva,diva,"{'gamma_y': 10e5, 'gamma_d': 1e5}" diff --git a/docs/.nojekyll b/docs/.nojekyll index 8b1378917..e69de29bb 100644 --- a/docs/.nojekyll +++ b/docs/.nojekyll @@ -1 +0,0 @@ - diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo deleted file mode 100644 index ab3556479..000000000 --- a/docs/build/html/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 89930ac99471c05d552b23fb61346fee -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_images/libDG.svg b/docs/build/html/_images/libDG.svg deleted file mode 100644 index 966bed82d..000000000 --- a/docs/build/html/_images/libDG.svg +++ /dev/null @@ -1,207 +0,0 @@ -taskalgostrainerobservermodel_selectiondatasetmodelcomponentsexperimentTaskdim_yTaskFolderAlgoBuilderConcreteAlgoBuilderTrainerObserverModelSelDatasetget__itemModelint dim_yint dim_dModelBuilderbuild_part_a()build_part_b()ConcreteModelConcreteModelBuildercommon_networkspatternsExperimentTaskHandler \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/a_algo_builder.html b/docs/build/html/_modules/domainlab/algos/a_algo_builder.html deleted file mode 100644 index eb7fdc0e7..000000000 --- a/docs/build/html/_modules/domainlab/algos/a_algo_builder.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.a_algo_builder — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.a_algo_builder

-from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler
-
-
-
[docs]class NodeAlgoBuilder(AbstractChainNodeHandler): - """ - Base class for Algorithm Builder - """ - na_prefix = "NodeAlgoBuilder" - -
[docs] def dset_decoration_args_algo(self, args, ddset): - """ - most algorithms do not need re-organization of data feed flow like JiGen and MatchDG - """ - print("processing dataset for ", args.aname) - return ddset
- - @property - def name(self): - """ - get the name of the algorithm - """ - na_prefix = NodeAlgoBuilder.na_prefix - len_prefix = len(na_prefix) - na_class = type(self).__name__ - if na_class[:len_prefix] != na_prefix: - raise RuntimeError( - "algorithm builder node class must start with ", na_prefix, - "the current class is named: ", na_class) - return type(self).__name__[len_prefix:].lower() - -
[docs] def is_myjob(self, request): - """ - :param request: string - """ - return request == self.name
- -
[docs] def init_business(self, exp): - raise NotImplementedError
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_custom.html b/docs/build/html/_modules/domainlab/algos/builder_custom.html deleted file mode 100644 index f22f72815..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_custom.html +++ /dev/null @@ -1,407 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_custom — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_custom

-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.trainers.train_basic import TrainerBasic
-from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter
-from domainlab.utils.utils_cuda import get_device
-
-
-
[docs]def make_basic_trainer(class_name_model): - """make_basic_trainer. - :param class_name_model: - """ - class NodeAlgoBuilderCustom(NodeAlgoBuilder): - """NodeAlgoBuilderCustom.""" - def _set_args(self, args, val_arg_na, prefix, argname): - """_set_args. - Since we could not hard code all possible strings in the argparser, - we add attributes to args name space according to the user - specification from the custom python file they provide - - the custom model the user wrote should have - model.dict_net_module_na2arg_na with something like - {"net1":"name1", "net2":"name2"} - val_arg_na below will be filled with "name1" for instance - - python main_out.py –te_d=caltech –task=mini_vlcs –debug –bs=3 - –apath=examples/algos/demo_custom_model.py - –aname=custom –nname_argna2val net1 –nname_argna2val alexnet - - :param args: the namespace of command line arguemnts - :param val_arg_na: the custom argument name the user specified - :param prefix: nname or npath to be consistent with the rest of - the package - :param argname: nname_argna2val or "npath_argna2val", hard coded - """ - if getattr(args, argname) is None: - setattr(args, prefix+val_arg_na, None) - return - list_args = getattr(args, argname) - ind = list_args.index(val_arg_na) - if ind+1 >= len(list_args): # list of args always even length - raise RuntimeError("\n nname_argna2val or npath_argna2val should \ - \n always be specified in pairs instead of \ - odd number:\ - \n %s" % ( - str(list_args))) - val = list_args[ind+1] - # add attributes to namespaces args, the attributes are provided by - # user in the custom model file - setattr(args, prefix+val_arg_na, val) - - def set_nets_from_dictionary(self, args, task, model): - """set_nets_from_dictionary. - the custom model the user wrote should have - model.dict_net_module_na2arg_na with something like - {"net1":"name1", "net2":"name2"} - python main_out.py –te_d=caltech –task=mini_vlcs –debug –bs=3 - –apath=examples/algos/demo_custom_model.py - –aname=custom –nname_argna2val net1 –nname_argna2val alexnet - """ - for key_module_na, val_arg_na in \ - model.dict_net_module_na2arg_na.items(): - # - if args.nname_argna2val is None and \ - args.npath_argna2val is None: - raise RuntimeError("either specify nname_argna2val or \ - npath_argna2val") - self._set_args(args, val_arg_na, "nname", "nname_argna2val") - self._set_args(args, val_arg_na, "npath", "npath_argna2val") - # - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname"+val_arg_na, - arg_path_of_net="npath"+val_arg_na)() - - net = builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, i_h=task.isize.i_h, i_w=task.isize.i_w) - model.add_module("%s" % (key_module_na), net) - - def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, model_sel, device) - model = class_name_model(list_str_y=task.list_str_y) - self.set_nets_from_dictionary(args, task, model) - trainer = TrainerBasic(model, task, observer, device, args) - return trainer - return NodeAlgoBuilderCustom
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_dann.html b/docs/build/html/_modules/domainlab/algos/builder_dann.html deleted file mode 100644 index d08d73158..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_dann.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_dann — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_dann

-"""
-builder for Domain Adversarial Neural Network: accept different training scheme
-"""
-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp
-from domainlab.algos.trainers.train_visitor import TrainerVisitor
-from domainlab.algos.trainers.train_visitor import HyperSchedulerAneal
-from domainlab.algos.trainers.train_dial import TrainerDIAL
-from domainlab.compos.nn_zoo.net_classif import ClassifDropoutReluLinear
-from domainlab.compos.utils_conv_get_flat_dim import get_flat_dim
-from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter
-from domainlab.models.model_dann import mk_dann
-from domainlab.utils.utils_cuda import get_device
-
-
-
[docs]class NodeAlgoBuilderDANN(NodeAlgoBuilder): - """ - NodeAlgoBuilderDANN - """ -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - msel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, msel, device) - observer = ObVisitorCleanUp(observer) - - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, @FIXME, constant string - - net_encoder = builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_w=task.isize.i_w, - i_h=task.isize.i_h) - - dim_feat = get_flat_dim(net_encoder, - task.isize.i_c, - task.isize.i_h, - task.isize.i_w) - - net_classifier = ClassifDropoutReluLinear(dim_feat, task.dim_y) - net_discriminator = ClassifDropoutReluLinear( - dim_feat, len(task.list_domain_tr)) - - model = mk_dann()(list_str_y=task.list_str_y, - list_str_d=task.list_domain_tr, - alpha=args.gamma_reg, - net_encoder=net_encoder, - net_classifier=net_classifier, - net_discriminator=net_discriminator) - if args.trainer == "dial": - trainer = TrainerDIAL(model, task, observer, device, args) - elif args.trainer is None: - trainer = TrainerVisitor(model, task, observer, device, args) - trainer.set_scheduler(HyperSchedulerAneal, - total_steps=trainer.num_batches*args.epos, - flag_update_epoch=False, - flag_update_batch=True) - else: - raise RuntimeError("no other trainer supported yet for the selected algorithm") - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_deepall.html b/docs/build/html/_modules/domainlab/algos/builder_deepall.html deleted file mode 100644 index 27dd07088..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_deepall.html +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_deepall — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_deepall

-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.trainers.train_basic import TrainerBasic
-from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter
-from domainlab.models.model_deep_all import mk_deepall
-from domainlab.utils.utils_cuda import get_device
-
-
-
[docs]class NodeAlgoBuilderDeepAll(NodeAlgoBuilder): -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, model_sel, device) - - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME, constant string - - net = builder.init_business(flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_h=task.isize.i_h, - i_w=task.isize.i_w) - - model = mk_deepall()(net, list_str_y=task.list_str_y) - trainer = TrainerBasic(model, task, observer, device, args) - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_dial.html b/docs/build/html/_modules/domainlab/algos/builder_dial.html deleted file mode 100644 index 877bbb758..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_dial.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_dial — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_dial

-"""
-builder for domain invariant adversarial learning
-"""
-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.trainers.train_dial import TrainerDIAL
-from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter
-from domainlab.models.model_deep_all import mk_deepall
-from domainlab.utils.utils_cuda import get_device
-
-
-
[docs]class NodeAlgoBuilderDeepAll_DIAL(NodeAlgoBuilder): - """ - builder for domain invariant adversarial learning - """ -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, model_sel, device) - - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME, constant string - - net = builder.init_business(flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_h=task.isize.i_h, - i_w=task.isize.i_w) - - model = mk_deepall()(net, list_str_y=task.list_str_y) - trainer = TrainerDIAL(model, task, observer, device, args) - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_diva.html b/docs/build/html/_modules/domainlab/algos/builder_diva.html deleted file mode 100644 index 3f95ce3ae..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_diva.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_diva — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_diva

-"""
-Builder pattern to build different component for experiment with DIVA
-"""
-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp
-from domainlab.algos.observers.c_obvisitor_gen import ObVisitorGen
-from domainlab.algos.trainers.train_visitor import TrainerVisitor
-from domainlab.algos.trainers.train_dial import TrainerDIAL
-
-from domainlab.compos.pcr.request import RequestVAEBuilderCHW
-from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter
-from domainlab.models.model_diva import mk_diva
-from domainlab.utils.utils_cuda import get_device
-
-
-
[docs]class NodeAlgoBuilderDIVA(NodeAlgoBuilder): - """ - Builder pattern to build different component for experiment with DIVA - """ -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - request = RequestVAEBuilderCHW( - task.isize.c, task.isize.h, task.isize.w, args) - node = VAEChainNodeGetter(request)() - model = mk_diva()(node, - zd_dim=args.zd_dim, - zy_dim=args.zy_dim, - zx_dim=args.zx_dim, - list_str_y=task.list_str_y, - list_d_tr=task.list_domain_tr, - gamma_d=args.gamma_d, - gamma_y=args.gamma_y, - beta_x=args.beta_x, - beta_y=args.beta_y, - beta_d=args.beta_d) - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - if not args.gen: - observer = ObVisitorCleanUp( - ObVisitor(exp, - model_sel, - device)) - else: - observer = ObVisitorCleanUp( - ObVisitorGen(exp, - model_sel, - device)) - if args.trainer == "dial": - trainer = TrainerDIAL(model, task, observer, device, args) - elif args.trainer is None: - trainer = TrainerVisitor(model, task, observer, device, args) - else: - raise NotImplementedError("diva does not support trainers other than default and dial") - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_hduva.html b/docs/build/html/_modules/domainlab/algos/builder_hduva.html deleted file mode 100644 index fd8ffa535..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_hduva.html +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_hduva — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_hduva

-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp
-from domainlab.algos.trainers.train_visitor import TrainerVisitor
-from domainlab.compos.pcr.request import RequestVAEBuilderCHW
-from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter
-from domainlab.models.model_hduva import mk_hduva
-from domainlab.utils.utils_cuda import get_device
-
-
-
[docs]class NodeAlgoBuilderHDUVA(NodeAlgoBuilder): - """ - NodeAlgoBuilderHDUVA - """ -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - request = RequestVAEBuilderCHW( - task.isize.c, task.isize.h, task.isize.w, args) - device = get_device(args.nocu) - node = VAEChainNodeGetter(request, args.topic_dim)() - model = mk_hduva()(node, - zd_dim=args.zd_dim, - zy_dim=args.zy_dim, - zx_dim=args.zx_dim, - device=device, - topic_dim=args.topic_dim, - list_str_y=task.list_str_y, - list_d_tr=task.list_domain_tr, - gamma_d=args.gamma_d, - gamma_y=args.gamma_y, - beta_t=args.beta_t, - beta_x=args.beta_x, - beta_y=args.beta_y, - beta_d=args.beta_d) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitorCleanUp( - ObVisitor(exp, model_sel, device)) - trainer = TrainerVisitor(model, task, observer, device, args) - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_jigen1.html b/docs/build/html/_modules/domainlab/algos/builder_jigen1.html deleted file mode 100644 index 771d3ef55..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_jigen1.html +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_jigen1 — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_jigen1

-"""
-builder for JiGen
-"""
-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp
-from domainlab.algos.trainers.train_visitor import TrainerVisitor
-from domainlab.algos.trainers.train_visitor import HyperSchedulerAneal
-from domainlab.compos.nn_zoo.net_classif import ClassifDropoutReluLinear
-from domainlab.compos.utils_conv_get_flat_dim import get_flat_dim
-from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter
-from domainlab.models.model_jigen import mk_jigen
-from domainlab.utils.utils_cuda import get_device
-from domainlab.dsets.utils_wrapdset_patches import WrapDsetPatches
-
-
-
[docs]class NodeAlgoBuilderJiGen(NodeAlgoBuilder): - """ - NodeAlgoBuilderJiGen - """ -
[docs] def dset_decoration_args_algo(self, args, ddset): - """ - JiGen need to shuffle the tiles of the original image - """ - ddset = WrapDsetPatches(ddset, - num_perms2classify=args.nperm, - prob_no_perm=1-args.pperm, - grid_len=args.grid_len, - ppath=args.jigen_ppath) - return ddset
- -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - msel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, msel, device) - observer = ObVisitorCleanUp(observer) - - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, @FIXME, constant string - - net_encoder = builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_w=task.isize.i_w, - i_h=task.isize.i_h) - - dim_feat = get_flat_dim(net_encoder, - task.isize.i_c, - task.isize.i_h, - task.isize.i_w) - - net_classifier = ClassifDropoutReluLinear(dim_feat, task.dim_y) - - # @FIXME: this seems to be the only difference w.r.t. builder_dann - net_classifier_perm = ClassifDropoutReluLinear( - dim_feat, args.nperm+1) - model = mk_jigen()(list_str_y=task.list_str_y, - list_str_d=task.list_domain_tr, - coeff_reg=args.gamma_reg, - net_encoder=net_encoder, - net_classifier_class=net_classifier, - net_classifier_permutation=net_classifier_perm) - - trainer = TrainerVisitor(model, task, observer, device, args) - trainer.set_scheduler(HyperSchedulerAneal, - total_steps=trainer.num_batches*args.epos, - flag_update_epoch=False, - flag_update_batch=True) - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/builder_matchdg.html b/docs/build/html/_modules/domainlab/algos/builder_matchdg.html deleted file mode 100644 index d18b545a8..000000000 --- a/docs/build/html/_modules/domainlab/algos/builder_matchdg.html +++ /dev/null @@ -1,377 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.builder_matchdg — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.builder_matchdg

-from domainlab.algos.a_algo_builder import NodeAlgoBuilder
-from domainlab.algos.msels.c_msel import MSelTrLoss
-from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor
-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.algos.trainers.train_matchdg import TrainerMatchDG
-from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter
-from domainlab.models.model_deep_all import mk_deepall
-from domainlab.models.wrapper_matchdg import ModelWrapMatchDGLogit
-from domainlab.utils.utils_cuda import get_device
-from domainlab.tasks.utils_task_dset import DsetIndDecorator4XYD
-
-
-
[docs]class NodeAlgoBuilderMatchDG(NodeAlgoBuilder): - """ - algorithm builder for matchDG - """ -
[docs] def dset_decoration_args_algo(self, args, ddset): - ddset = DsetIndDecorator4XYD(ddset) - return ddset
- -
[docs] def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - - erm_builder = FeatExtractNNBuilderChainNodeGetter( - args, - arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME: constant string - erm_net = erm_builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, i_h=task.isize.i_h, - i_w=task.isize.i_w) - - model = mk_deepall()(erm_net, list_str_y=task.list_str_y) - model = ModelWrapMatchDGLogit(model, list_str_y=task.list_str_y) - - model = model.to(device) - ctr_builder = FeatExtractNNBuilderChainNodeGetter( - args, - arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME constant string - ctr_net = ctr_builder.init_business( - flag_pretrain=True, - dim_out=task.dim_y, - # @FIXME: ctr_model should not rely on task.dim_y so it could - # support more tasks? maybe use task.feat_num? - remove_last_layer=True, - args=args, - i_c=task.isize.i_c, - i_h=task.isize.i_h, - i_w=task.isize.i_w) - ctr_model = ctr_net.to(device) - - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, - model_sel, - device) - trainer = TrainerMatchDG(exp, task, ctr_model, model, observer, args, - device) - return trainer
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/compos/matchdg_args.html b/docs/build/html/_modules/domainlab/algos/compos/matchdg_args.html deleted file mode 100644 index b37531bee..000000000 --- a/docs/build/html/_modules/domainlab/algos/compos/matchdg_args.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.compos.matchdg_args — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.compos.matchdg_args

-
[docs]def add_args2parser_matchdg(parser): - # parser = argparse.ArgumentParser() - parser.add_argument('--tau', type=int, default=0.05, - help='factor to magnify cosine similarity') - parser.add_argument('--epos_per_match_update', type=int, default=5, - help='Number of epochs before updating the match tensor') - parser.add_argument('--epochs_ctr', type=int, default=None, - help='Total number of epochs for ctr') - parser.add_argument('--epochs_erm', type=int, default=None, - help='Total number of epochs for erm') - parser.add_argument('--penalty_ws', type=float, default=0.1, - help='Penalty weight for Matching Loss') - # args = parser.parse_args("") - # return args - return parser
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/compos/matchdg_base.html b/docs/build/html/_modules/domainlab/algos/compos/matchdg_base.html deleted file mode 100644 index d1c7dd3e1..000000000 --- a/docs/build/html/_modules/domainlab/algos/compos/matchdg_base.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.compos.matchdg_base — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.compos.matchdg_base

-import torch
-from torch import optim
-from domainlab.algos.compos.matchdg_match import MatchPair
-
-
-
[docs]class MatchAlgoBase(): - def __init__(self, task, phi, args, device, exp): - self.bs_match = args.bs # use the same batch size for match tensor - self.exp = exp - self.task = task - self.num_domain_tr = len(self.task.list_domain_tr) - train_domains = self.task.list_domain_tr - self.list_tr_domain_size = [len(self.task.dict_dset[key]) \ - for key in train_domains] - # so that order is kept! - self.base_domain_size = get_base_domain_size4match_dg(self.task) - self.dim_y = task.dim_y - - self.args = args - # @FIXME: training loader always drop the last batch, - # so inside matchdg, for the data storage tensor, - # loader is re-initialized by disabling drop - self.loader = task.loader_tr - self.device = device - self.phi = phi.to(self.device) - # - self.opt = self.get_opt_sgd() - self.scheduler = torch.optim.lr_scheduler.StepLR(self.opt, step_size=25) - self.ctr_mpath = self.exp.visitor.model_path + "_ctr" - # - self.tensor_ref_domain2each_domain_x = None - self.tensor_ref_domain2each_domain_y = None - -
[docs] def init_erm_phase(self): - """ - loade model from disk after training - the ctr(contrastive learning) phase - """ - # the keys of :attr:`state_dict` must exactly match the - # keys returned by this module's - # :meth:`~torch.nn.Module.state_dict` function - self.phi.load_state_dict(torch.load(self.ctr_mpath), strict=False) - # load the phi network trained during the - # ctr(contrastive learning) phase - self.phi = self.phi.to(self.device) - # len((ctr_phi.state_dict()).keys()): 122, - # extra fields are fc.weight, fc.bias - self.phi.eval() # @FIXME - self.mk_match_tensor(epoch=0)
- -
[docs] def get_opt_sgd(self): - opt = optim.SGD([{'params': filter( - lambda p: p.requires_grad, - self.phi.parameters())}, ], - lr=self.args.lr, weight_decay=5e-4, - momentum=0.9, nesterov=True) - return opt
- -
[docs] def save_model_ctr_phase(self): - # Store the weights of the model - # dirname = os.path.dirname(self.ctr_mpath) - # Path(dirname).mkdir(parents=True, exist_ok=True) - torch.save(self.phi.state_dict(), self.ctr_mpath)
- -
[docs] def save_model_erm_phase(self): - torch.save(self.phi, self.exp.visitor.model_path)
- -
[docs] def mk_match_tensor(self, epoch): - """ - initialize or update match tensor - """ - obj_match = MatchPair(self.dim_y, - self.task.isize.i_c, - self.task.isize.i_h, - self.task.isize.i_w, - self.bs_match, - virtual_ref_dset_size=self.base_domain_size, - num_domains_tr=self.num_domain_tr, - list_tr_domain_size=self.list_tr_domain_size) - - # @FIXME: what is the usefulness of (epoch > 0) as argument - self.tensor_ref_domain2each_domain_x, self.tensor_ref_domain2each_domain_y = \ - obj_match(self.device, self.loader, self.phi, (epoch > 0))
- - -
[docs]def get_base_domain_size4match_dg(task): - """ - Base domain is a dataset where each class - set come from one of the nominal domains - """ - # @FIXME: base domain should be calculated only on training domains - # instead of all the domains! - # domain_keys = task.get_list_domains() - domain_keys = task.list_domain_tr - base_domain_size = 0 - classes = task.list_str_y - for mclass in classes: - num = 0 - ref_domain = -1 - for _, domain_key in enumerate(domain_keys): - if task.dict_domain_class_count[domain_key][mclass] > num: - ref_domain = domain_key - num = task.dict_domain_class_count[domain_key][mclass] - print("for class ", mclass, " bigest sample size is ", - num, "ref domain is", ref_domain) - base_domain_size += num - return base_domain_size
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/compos/matchdg_ctr_erm.html b/docs/build/html/_modules/domainlab/algos/compos/matchdg_ctr_erm.html deleted file mode 100644 index 0b19d04bd..000000000 --- a/docs/build/html/_modules/domainlab/algos/compos/matchdg_ctr_erm.html +++ /dev/null @@ -1,559 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.compos.matchdg_ctr_erm — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.compos.matchdg_ctr_erm

-import torch
-
-from domainlab.algos.compos.matchdg_base import MatchAlgoBase
-from domainlab.algos.compos.matchdg_utils import (dist_cosine_agg,
-                                                  dist_pairwise_cosine)
-
-
-
[docs]class MatchCtrErm(MatchAlgoBase): - """ - Contrastive Learning - """ - def __init__(self, task, phi, args, device, exp, flag_erm=False): - """ - """ - super().__init__(task, phi, args, device, exp) - self.epo_loss_tr = 0 - self.flag_erm = flag_erm - self.epos = self.args.epochs_ctr - self.epos_per_match = self.args.epos_per_match_update - self.str_phase = "ctr" - self.lambda_ctr = 1.0 - if self.flag_erm: - self.lambda_ctr = self.args.penalty_ws - self.epos = self.args.epochs_erm - self.str_phase = "erm" - self.init_erm_phase() - else: - self.mk_match_tensor(epoch=0) - -
[docs] def train(self): - for epoch in range(self.epos): - self.tr_epoch(epoch)
- -
[docs] def tr_epoch(self, epoch): - """ - # data in one batch comes from two sources: one part from loader, - # the other part from match tensor - """ - self.epo_loss_tr = 0 - print(self.str_phase, "epoch", epoch) - # update match tensor - if (epoch + 1) % self.epos_per_match == 0: - self.mk_match_tensor(epoch) - - inds_shuffle = torch.randperm(self.tensor_ref_domain2each_domain_x.size(0)) - # NOTE: match tensor size: N(ref domain size) * #(train domains) * (image size: c*h*w) - # self.tensor_ref_domain2each_domain_x[inds_shuffle] shuffles the match tensor at the first dimension - tuple_tensor_refdomain2each = torch.split(self.tensor_ref_domain2each_domain_x[inds_shuffle], - self.args.bs, dim=0) - # Splits the tensor into chunks. Each chunk is a view of the original tensor of batch size self.args.bs - # return is a tuple of the splited chunks - tuple_tensor_ref_domain2each_y = torch.split(self.tensor_ref_domain2each_domain_y[inds_shuffle], - self.args.bs, dim=0) - print("number of batches in match tensor: ", len(tuple_tensor_refdomain2each)) - print("single batch match tensor size: ", tuple_tensor_refdomain2each[0].shape) - - for batch_idx, (x_e, y_e, d_e, *_) in enumerate(self.loader): - # random loader with same batch size as the match tensor loader - # the 4th output of self.loader is not used at all, - # is only used for creating the match tensor - self.opt.zero_grad() - x_e = x_e.to(self.device) # 64 * 1 * 224 * 224 - # y_e_scalar = torch.argmax(y_e, dim=1).to(self.device) - y_e = y_e.to(self.device) - # d_e = torch.argmax(d_e, dim=1).numpy() - d_e = d_e.to(self.device) - # for each batch, the list loss is re-initialized - - # CTR (contrastive) loss for CTR/ERM phase are different - list_batch_loss_ctr = [] - # for a single batch, loss need to be - # aggregated across different combinations of domains. - # Defining a leaf node can cause problem by loss_ctr += xxx, - # a list with python built-in "sum" can aggregate - # these losses within one batch - - if self.flag_erm: - # logit_yhat = self.phi(x_e) # @FIXME - # loss_erm_rnd_loader = F.cross_entropy(logit_yhat, y_e.long()).to(self.device) - loss_erm_rnd_loader = self.phi.cal_loss(x_e, y_e, d_e) - - num_batches = len(tuple_tensor_refdomain2each) - - if batch_idx >= num_batches: - print("ref/base domain vs each domain match \ - traversed one sweep, starting new epoch") - break - - curr_batch_size = tuple_tensor_refdomain2each[batch_idx].shape[0] - - batch_tensor_ref_domain2each = tuple_tensor_refdomain2each[batch_idx].to(self.device) - # make order 5 tensor: (ref_domain, domain, channel, img_h, img_w) - # with first dimension as batch size - - # clamp the first two dimensions so the phi network could map image to feature - batch_tensor_ref_domain2each = batch_tensor_ref_domain2each.view( - batch_tensor_ref_domain2each.shape[0]*batch_tensor_ref_domain2each.shape[1], - batch_tensor_ref_domain2each.shape[2], # channel - batch_tensor_ref_domain2each.shape[3], # img_h - batch_tensor_ref_domain2each.shape[4]) # img_w - # now batch_tensor_ref_domain2each first dim will not be batch_size! - # batch_tensor_ref_domain2each.shape torch.Size([40, channel, 224, 224]) - - # @FIXME: change to extract_feature? - batch_feat_ref_domain2each = self.phi(batch_tensor_ref_domain2each) - # batch_feat_ref_domain2each.shape torch.Size[40, 512] - # torch.sum(torch.isnan(batch_tensor_ref_domain2each)) - # assert not torch.sum(torch.isnan(batch_feat_ref_domain2each)) - flag_isnan = torch.any(torch.isnan(batch_feat_ref_domain2each)) - if flag_isnan: - # usually because learning rate is too big - raise RuntimeError("batch_feat_ref_domain2each NAN!") - - # for contrastive training phase, - # the last layer of the model is replaced with identity - - batch_ref_domain2each_y = tuple_tensor_ref_domain2each_y[batch_idx].to(self.device) - batch_ref_domain2each_y = batch_ref_domain2each_y.view(batch_ref_domain2each_y.shape[0]*batch_ref_domain2each_y.shape[1]) - - # @FIXME: - # self.phi.cal_loss(batch_tensor_ref_domain2each, - # batch_ref_domain2each_y) - - if self.flag_erm: - # loss_erm_match_tensor = F.cross_entropy(batch_feat_ref_domain2each, batch_ref_domain2each_y.long()).to(self.device) - # @FIXME: check if batch_ref_domain2each_y is - # continuous number which means it is at its initial value, - # not yet filled - # FIMXE: shall we leave batch_ref_domain2each_y scalar so it - # takes less memory? - loss_erm_match_tensor = self.phi.cal_loss(batch_tensor_ref_domain2each, batch_ref_domain2each_y.long()) - - # Creating tensor of shape (domain size, total domains, feat size ) - # The match tensor's first two dimension - # [(Ref domain size) * (# train domains)] - # has been clamped together to get features extracted - # through self.phi - - # it has to be reshaped into the match tensor shape, the same - # for the extracted feature here, it has to reshaped into - # the shape of the match tensor - # to make sure that the reshape only happens at the - # first two dimension, the feature dim has to be kept intact - dim_feat = batch_feat_ref_domain2each.shape[1] - batch_feat_ref_domain2each = batch_feat_ref_domain2each.view(curr_batch_size, self.num_domain_tr, dim_feat) - - batch_ref_domain2each_y = batch_ref_domain2each_y.view(curr_batch_size, self.num_domain_tr) - - # The match tensor's first two dimension - # [(Ref domain size) * (# train domains)] has been clamped - # together to get features extracted through self.phi - batch_tensor_ref_domain2each = \ - batch_tensor_ref_domain2each.view(curr_batch_size, - self.num_domain_tr, - batch_tensor_ref_domain2each.shape[1], # channel - batch_tensor_ref_domain2each.shape[2], # img_h - batch_tensor_ref_domain2each.shape[3]) # img_w - - # Contrastive Loss: class \times domain \times domain - counter_same_cls_diff_domain = 1 - for y_c in range(self.dim_y): - - subset_same_cls = (batch_ref_domain2each_y[:, 0] == y_c) - subset_diff_cls = (batch_ref_domain2each_y[:, 0] != y_c) - feat_same_cls = batch_feat_ref_domain2each[subset_same_cls] - feat_diff_cls = batch_feat_ref_domain2each[subset_diff_cls] - #print('class', y_c, "with same class and different class: ", - # feat_same_cls.shape[0], feat_diff_cls.shape[0]) - - if feat_same_cls.shape[0] == 0 or feat_diff_cls.shape[0] == 0: - # print("no instances of label", - # y_c, - # "in the current batch, continue") - continue - - if torch.sum(torch.isnan(feat_diff_cls)): - raise RuntimeError('feat_diff_cls has nan entrie(s)') - - feat_diff_cls = feat_diff_cls.view( - feat_diff_cls.shape[0]*feat_diff_cls.shape[1], - feat_diff_cls.shape[2]) - - for d_i in range(feat_same_cls.shape[1]): - dist_diff_cls_same_domain = dist_pairwise_cosine( - feat_same_cls[:, d_i, :], feat_diff_cls[:, :]) - - if torch.sum(torch.isnan(dist_diff_cls_same_domain)): - raise RuntimeError('dist_diff_cls_same_domain NAN') - - # iterate other domains - for d_j in range(feat_same_cls.shape[1]): - if d_i >= d_j: - continue - dist_same_cls_diff_domain = dist_cosine_agg(feat_same_cls[:, d_i, :], - feat_same_cls[:, d_j, :]) - - if torch.sum(torch.isnan(dist_same_cls_diff_domain)): - raise RuntimeError('dist_same_cls_diff_domain NAN') - - # CTR (contrastive) loss is exclusive for - # CTR phase and ERM phase - - if self.flag_erm: - list_batch_loss_ctr.append(torch.sum(dist_same_cls_diff_domain)) - else: - i_dist_same_cls_diff_domain = 1.0 - dist_same_cls_diff_domain - i_dist_same_cls_diff_domain = i_dist_same_cls_diff_domain / self.args.tau - partition = torch.log(torch.exp(i_dist_same_cls_diff_domain) + dist_diff_cls_same_domain) - list_batch_loss_ctr.append(-1 * torch.sum(i_dist_same_cls_diff_domain - partition)) - - counter_same_cls_diff_domain += dist_same_cls_diff_domain.shape[0] - - loss_ctr = sum(list_batch_loss_ctr) / counter_same_cls_diff_domain - - coeff = (epoch + 1)/(self.epos + 1) - # loss aggregation is over different domain - # combinations of the same batch - # https://discuss.pytorch.org/t/leaf-variable-was-used-in-an-inplace-operation/308 - # Loosely, tensors you create directly are leaf variables. - # Tensors that are the result of a differentiable operation are - # not leaf variables - - if self.flag_erm: - # extra loss of ERM phase: the ERM loss - # (the CTR loss for the ctr phase and erm phase are different) - # erm loss comes from two different data loaders, - # one is rnd (random) data loader - # the other one is the data loader from the match tensor - loss_e = torch.tensor(0.0, requires_grad=True) + \ - torch.mean(loss_erm_rnd_loader) + \ - torch.mean(loss_erm_match_tensor) + \ - self.lambda_ctr * coeff * loss_ctr - else: - loss_e = torch.tensor(0.0, requires_grad=True) + \ - self.lambda_ctr * coeff * loss_ctr - # @FIXME: without torch.tensor(0.0), after a few epochs, - # error "'float' object has no attribute 'backward'" - - loss_e.backward(retain_graph=False) - self.opt.step() - self.epo_loss_tr += loss_e.detach().item() - - torch.cuda.empty_cache() - - if not self.flag_erm: - # Save ctr model's weights post each epoch - self.save_model_ctr_phase()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/compos/matchdg_match.html b/docs/build/html/_modules/domainlab/algos/compos/matchdg_match.html deleted file mode 100644 index 3aa99ea77..000000000 --- a/docs/build/html/_modules/domainlab/algos/compos/matchdg_match.html +++ /dev/null @@ -1,599 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.compos.matchdg_match — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.compos.matchdg_match

-import warnings
-
-import numpy as np
-import torch
-
-from domainlab.algos.compos.matchdg_utils import (
-    MatchDictNumDomain2SizeDomain, MatchDictVirtualRefDset2EachDomain)
-from domainlab.tasks.utils_task import mk_loader
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]class MatchPair(): - @store_args - def __init__(self, - dim_y, # @TODO: dim_y is not used here - i_c, - i_h, - i_w, - bs_match, # @TODO: bs_match is not used here - virtual_ref_dset_size, - num_domains_tr, - list_tr_domain_size): - """ - :param virtual_ref_dset_size: sum of biggest class sizes - :param num_domains_tr: - :param list_tr_domain_size: - :param phi: neural network to generate causal features from input - """ - self.dict_cls_ind_base_domain_ind = {} - self.dict_virtual_dset2each_domain = MatchDictVirtualRefDset2EachDomain( - virtual_ref_dset_size=virtual_ref_dset_size, - num_domains_tr=num_domains_tr, - i_c=i_c, i_h=i_h, i_w=i_w)() - - self.dict_domain_data = MatchDictNumDomain2SizeDomain( - num_domains_tr=num_domains_tr, - list_tr_domain_size=list_tr_domain_size, - i_c=i_c, i_h=i_h, i_w=i_w)() - - self.indices_matched = {} - for key in range(virtual_ref_dset_size): - self.indices_matched[key] = [] - self.perfect_match_rank = [] - - self.domain_count = {} - for domain in range(num_domains_tr): - self.domain_count[domain] = 0 - - def _fill_data(self, loader): - """ - copy all data from loader, then store them in memory - variable self.dict_domain_data - """ - # NOTE: loader contains data from several dataset - list_idx_several_ds = [] - loader_full_data = mk_loader( - loader.dataset, - bsize=loader.batch_size, - drop_last=False) - # @FIXME: training loader will always drop the last incomplete batch - for _, (x_e, y_e, d_e, idx_e) in enumerate(loader_full_data): - # traverse mixed domain data from loader - list_idx_several_ds.extend(list(idx_e.cpu().numpy())) - x_e = x_e - y_e = torch.argmax(y_e, dim=1) - d_e = torch.argmax(d_e, dim=1).numpy() - - # get all domains in current batch - unique_domains = np.unique(d_e) - for domain_idx in unique_domains: - # select all instances belong to one domain - flag_curr_domain = (d_e == domain_idx) - - # flag_curr_domain is subset indicator of - # True of False for selection of data from the mini-batch - - # get global index of all instances of the current domain - global_indices = idx_e[flag_curr_domain] - - # global_indices are subset of idx_e, which contains - # global index of data from the loader - for local_ind in range(global_indices.shape[0]): - # @FIXME: the following is just coping all data to - # self.dict_domain_data (in memory with ordering), - # which seems redundant - - # tensor.item get the scalar - global_ind = global_indices[local_ind].item() - self.dict_domain_data[domain_idx]['data'][global_ind] = \ - x_e[flag_curr_domain][local_ind] - # flag_curr_domain are subset indicator - # for selection of domain - self.dict_domain_data[domain_idx]['label'][global_ind] = \ - y_e[flag_curr_domain][local_ind] - # copy trainining batch to dict_domain_data - self.dict_domain_data[domain_idx]['idx'][global_ind] = \ - idx_e[flag_curr_domain][local_ind] - self.domain_count[domain_idx] += 1 - - # if all data has been re-organized(filled) into the current tensor - assert len(list_idx_several_ds) == len(loader.dataset) - # NOTE: check if self.dict_domain_data[domain_idx]['label'] has - # some instances that are initial continuous - # value instead of class label - for domain in range(self.num_domains_tr): - if self.domain_count[domain] != self.list_tr_domain_size[domain]: - warnings.warn("domain_count show matching \ - dictionary missing data!") - - def _cal_base_domain(self): - """ - # Determine the base_domain_idx as the domain - # with the max samples of the current class - # Create dictionary: class label -> list of ordered flag_curr_domain - """ - for y_c in range(self.dim_y): - base_domain_size = 0 - base_domain_idx = -1 - for domain_idx in range(self.num_domains_tr): - flag_curr_class = (self.dict_domain_data[domain_idx]['label'] == y_c) # tensor of True/False - curr_size = self.dict_domain_data[domain_idx]['label'][flag_curr_class].shape[0] # flag_curr_class are subset indicator - if base_domain_size < curr_size: - base_domain_size = curr_size - base_domain_idx = domain_idx - self.dict_cls_ind_base_domain_ind[y_c] = base_domain_idx - # for each class label, there is a base domain - print("for class", y_c) - print("domain index as base domain:", base_domain_idx) - print("Base Domain size", base_domain_size) - - - - def __call__(self, device, loader, phi, flag_match_min_dist): - self._fill_data(loader) - self._cal_base_domain() - for curr_domain_ind in range(self.num_domains_tr): - counter_ref_dset_size = 0 - for y_c in range(self.dim_y): - # which domain to use as the base domain for the current class - base_domain_idx = self.dict_cls_ind_base_domain_ind[y_c] - - # subset indicator - flags_base_domain_curr_cls = \ - (self.dict_domain_data[base_domain_idx]['label'] == y_c) - flags_base_domain_curr_cls = flags_base_domain_curr_cls[:, 0] - global_inds_base_domain_curr_cls = self.dict_domain_data[base_domain_idx]['idx'][flags_base_domain_curr_cls] - # pick out base domain class label y_c images - # the difference of this block is "curr_domain_ind" - # in iteration is - # used instead of base_domain_idx for current class - - # pick out current domain y_c class images - flag_curr_domain_curr_cls = (self.dict_domain_data[curr_domain_ind]['label'] == y_c) - # NO label matches y_c - flag_curr_domain_curr_cls = flag_curr_domain_curr_cls[:, 0] - global_inds_curr_domain_curr_cls = self.dict_domain_data[curr_domain_ind]['idx'][flag_curr_domain_curr_cls] - size_curr_domain_curr_cls = global_inds_curr_domain_curr_cls.shape[0] - if size_curr_domain_curr_cls == 0: # there is no class y_c in current domain - print("current domain", - curr_domain_ind, - " does not contain class ", y_c) - raise RuntimeError("current domain does not contain all classes") - - # compute base domain features for class label y_c - x_base_domain_curr_cls = self.dict_domain_data[base_domain_idx]['data'][flags_base_domain_curr_cls] - # pick out base domain class label y_c images - # split data into chunks - tuple_batch_x_base_domain_curr_cls = torch.split(x_base_domain_curr_cls, self.bs_match, dim=0) - # @FIXME. when x_base_domain_curr_cls is smaller - # than the self.bs_match, then there is only one batch - list_base_feat = [] - for batch_x_base_domain_curr_cls in tuple_batch_x_base_domain_curr_cls: - with torch.no_grad(): - batch_x_base_domain_curr_cls = batch_x_base_domain_curr_cls.to(device) - feat = phi(batch_x_base_domain_curr_cls) - list_base_feat.append(feat.cpu()) - tensor_feat_base_domain_curr_cls = torch.cat(list_base_feat) # base domain features - - if flag_match_min_dist: # if epoch > 0:flag_match_min_dist=True - x_curr_domain_curr_cls = self.dict_domain_data[curr_domain_ind]['data'][flag_curr_domain_curr_cls] - # indices_curr pick out current domain y_c class images - tuple_x_batch_curr_domain_curr_cls = torch.split(x_curr_domain_curr_cls, self.bs_match, dim=0) - list_feat_x_curr_domain_curr_cls = [] - for batch_feat in tuple_x_batch_curr_domain_curr_cls: - with torch.no_grad(): - batch_feat = batch_feat.to(device) - out = phi(batch_feat) - list_feat_x_curr_domain_curr_cls.append(out.cpu()) - tensor_feat_curr_domain_curr_cls = torch.cat(list_feat_x_curr_domain_curr_cls) - # feature through inference network for the current domain of class y_c - - tensor_feat_base_domain_curr_cls = tensor_feat_base_domain_curr_cls.unsqueeze(1) - tuple_feat_base_domain_curr_cls = torch.split(tensor_feat_base_domain_curr_cls, self.bs_match, dim=0) - - counter_curr_cls_base_domain = 0 - - # tuple_feat_base_domain_curr_cls is a tuple of splitted part - for feat_base_domain_curr_cls in tuple_feat_base_domain_curr_cls: - - if flag_match_min_dist: # if epoch > 0:flag_match_min_dist=True - # Need to compute over batches of - # feature due to device Memory out errors - # Else no need for loop over - # tuple_feat_base_domain_curr_cls; - # could have simply computed - # tensor_feat_curr_domain_curr_cls - - # tensor_feat_base_domain_curr_cls - dist_same_class_base_domain_curr_domain = torch.sum((tensor_feat_curr_domain_curr_cls - feat_base_domain_curr_cls)**2, dim=2) - # tensor_feat_curr_domain_curr_cls.shape torch.Size([184, 512]) - # feat_base_domain_curr_cls.shape torch.Size([64, 1, 512]) - # (tensor_feat_curr_domain_curr_cls - feat_base_domain_curr_cls).shape: torch.Size([64, 184, 512]) - # dist_same_class_base_domain_curr_domain.shape: - # torch.Size([64, 184]) is the per element distance of - # the cartesian product of feat_base_domain_curr_cls vs - # tensor_feat_curr_domain_curr_cls - match_ind_base_domain_curr_domain = torch.argmin(dist_same_class_base_domain_curr_domain, dim=1) # the batch index of the neareast neighbors - # len(match_ind_base_domain_curr_domain)=64 - # theoretically match_ind_base_domain_curr_domain can - # be a permutation of 0 to 183 though of size 64 - # sort_val, sort_idx = \ - # torch.sort(dist_same_class_base_domain_curr_domain, dim=1) - del dist_same_class_base_domain_curr_domain - - # feat_base_domain_curr_cls.shape torch.Size([64, 1, 512]) - for idx in range(feat_base_domain_curr_cls.shape[0]): - # counter_curr_cls_base_domain =0 at initialization - - ### global_inds_base_domain_curr_cls pick out base - # domain class label y_c images - global_pos_base_domain_curr_cls = global_inds_base_domain_curr_cls[counter_curr_cls_base_domain].item() - if curr_domain_ind == base_domain_idx: - ind_match_global_curr_domain_curr_cls = global_pos_base_domain_curr_cls - else: - if flag_match_min_dist: # if epoch > 0:match_min_dist=True - ind_match_global_curr_domain_curr_cls = global_inds_curr_domain_curr_cls[match_ind_base_domain_curr_domain[idx]].item() - else: # if epoch == 0 - ind_match_global_curr_domain_curr_cls = global_inds_curr_domain_curr_cls[counter_curr_cls_base_domain%size_curr_domain_curr_cls].item() - - self.dict_virtual_dset2each_domain[counter_ref_dset_size]['data'][curr_domain_ind] = self.dict_domain_data[curr_domain_ind]['data'][ind_match_global_curr_domain_curr_cls] - self.dict_virtual_dset2each_domain[counter_ref_dset_size]['label'][curr_domain_ind] = self.dict_domain_data[curr_domain_ind]['label'][ind_match_global_curr_domain_curr_cls] - # @FIXME: label initially were set to random continuous - # value, which is a technique to check if - # every data has been filled - counter_curr_cls_base_domain += 1 - counter_ref_dset_size += 1 - - if counter_ref_dset_size != self.virtual_ref_dset_size: - print("counter_ref_dset_size", counter_ref_dset_size) - print("self.virtual_ref_dset_size", self.virtual_ref_dset_size) - # warnings.warn("counter_ref_dset_size not equal to self.virtual_ref_dset_size") - raise RuntimeError("counter_ref_dset_size not equal to self.virtual_ref_dset_size") - - - for key in self.dict_virtual_dset2each_domain.keys(): - if self.dict_virtual_dset2each_domain[key]['label'].shape[0] != self.num_domains_tr: - raise RuntimeError("self.dict_virtual_dset2each_domain, \ - one key correspond to value tensor not \ - equal to number of training domains") - - # Sanity Check: Ensure paired points have the same class label - wrong_case = 0 - for key in self.dict_virtual_dset2each_domain.keys(): - for d_i in range(self.dict_virtual_dset2each_domain[key]['label'].shape[0]): - for d_j in range(self.dict_virtual_dset2each_domain[key]['label'].shape[0]): - if d_j > d_i: - if self.dict_virtual_dset2each_domain[key]['label'][d_i] != self.dict_virtual_dset2each_domain[key]['label'][d_j]: - # raise RuntimeError("the reference domain has 'rows' with inconsistent class labels") - wrong_case += 1 - print('Total Label MisMatch across pairs: ', wrong_case) - if wrong_case != 0: - raise RuntimeError("the reference domain \ - has 'rows' with inconsistent class labels") - - list_ref_domain_each_domain = [] - list_ref_domain_each_domain_label = [] - for ind_ref_domain_key in self.dict_virtual_dset2each_domain.keys(): - list_ref_domain_each_domain.append(self.dict_virtual_dset2each_domain[ind_ref_domain_key]['data']) - list_ref_domain_each_domain_label.append(self.dict_virtual_dset2each_domain[ind_ref_domain_key]['label']) - - tensor_ref_domain_each_domain_x = torch.stack(list_ref_domain_each_domain) - tensor_ref_domain_each_domain_label = torch.stack(list_ref_domain_each_domain_label) - - print(tensor_ref_domain_each_domain_x.shape, tensor_ref_domain_each_domain_label.shape) - - del self.dict_domain_data - del self.dict_virtual_dset2each_domain - return tensor_ref_domain_each_domain_x, tensor_ref_domain_each_domain_label
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/compos/matchdg_utils.html b/docs/build/html/_modules/domainlab/algos/compos/matchdg_utils.html deleted file mode 100644 index 5cc26203d..000000000 --- a/docs/build/html/_modules/domainlab/algos/compos/matchdg_utils.html +++ /dev/null @@ -1,413 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.compos.matchdg_utils — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.compos.matchdg_utils

-"""
-create dictionary for matching
-"""
-import torch
-
-
-
[docs]class MatchDictInit(): - """ - base class for matching dictionary creator - """ - def __init__(self, keys, vals, i_c, i_h, i_w): - self.keys = keys - self.vals = vals - self.i_c = i_c - self.i_h = i_h - self.i_w = i_w - -
[docs] def get_num_rows(self, key): - raise NotImplementedError
- - def __call__(self): - dict_data = {} - for key in self.keys: - dict_data[key] = {} - num_rows = self.get_num_rows(key) - dict_data[key]['data'] = torch.rand((num_rows, self.i_c, self.i_w, self.i_h)) - # @FIXME: some labels won't be filled at all, when using training loader since the incomplete batch is dropped - dict_data[key]['label'] = torch.rand((num_rows, 1)) # scalar label - dict_data[key]['idx'] = torch.randint(low=0, high=1, size=(num_rows, 1)) - return dict_data
- - -
[docs]class MatchDictVirtualRefDset2EachDomain(MatchDictInit): - """ - dict[0:virtual_ref_dset_size] has tensor dimension: (num_domains_tr, i_c, i_h, i_w) - """ - def __init__(self, virtual_ref_dset_size, num_domains_tr, i_c, i_h, i_w): - """ - virtual_ref_dset_size is a virtual dataset, len(virtual_ref_dset_size) = sum of all popular domains - """ - super().__init__(keys=range(virtual_ref_dset_size), vals=num_domains_tr, - i_c=i_c, i_h=i_h, i_w=i_w) - -
[docs] def get_num_rows(self, key=None): - """ - key is 0:virtual_ref_dset_size - """ - return self.vals # total_domains
- - -
[docs]class MatchDictNumDomain2SizeDomain(MatchDictInit): - """ - tensor dimension for the kth domain: [num_domains_tr, (size_domain_k, i_c, i_h, i_w)] - """ - def __init__(self, num_domains_tr, list_tr_domain_size, i_c, i_h, i_w): - super().__init__(keys=range(num_domains_tr), vals=list_tr_domain_size, - i_c=i_c, i_h=i_h, i_w=i_w) - -
[docs] def get_num_rows(self, key): - return self.vals[key] # list_tr_domain_size[domain_index]
- - -
[docs]def dist_cosine_agg(x1, x2): - """ - torch.nn.CosineSimilarity assumes x1 and x2 share exactly the same dimension - """ - fun_cos = torch.nn.CosineSimilarity(dim=1, eps=1e-08) - return 1.0 - fun_cos(x1, x2)
- -
[docs]def fun_tensor_normalize(tensor_batch_x): - eps = 1e-8 - batch_norm_x = tensor_batch_x.norm(dim=1) # Frobenius norm or Euclidean Norm long the embedding direction, len(norm) should be batch_size - batch_norm_x = batch_norm_x.view(batch_norm_x.shape[0], 1) # add dimension to tensor - tensor_eps = eps * torch.ones_like(batch_norm_x) - tensor_batch_x = tensor_batch_x / torch.max(batch_norm_x, tensor_eps) - assert not torch.sum(torch.isnan(tensor_batch_x)) - return tensor_batch_x
- - -
[docs]def dist_pairwise_cosine(x1, x2, tau=0.05): - """ - x1 and x2 does not necesarilly have the same shape, and we want to have a cartesian product of the pairwise distances - """ - assert len(x1.shape) == 2 and len(x2.shape) == 2 - assert not torch.sum(torch.isnan(x1)) - assert not torch.sum(torch.isnan(x2)) - - x1 = fun_tensor_normalize(x1) - x2 = fun_tensor_normalize(x2) - - x1_extended_dim = x1.unsqueeze(1) # Returns a new tensor with a dimension of size one inserted at the specified position. - # extend the order of by insering a new dimension so that cartesion product of pairwise distance can be calculated - - # since the batch size of x1 and x2 won't be the same, directly calculting elementwise product will cause an error - # with order 3 multiply order 2 tensor, the feature dimension will be matched then the rest dimensions form cartesian product - cos_sim = torch.sum(x1_extended_dim*x2, dim=2) # elementwise product - cos_sim = cos_sim / tau # make cosine similarity bigger than 1 - assert not torch.sum(torch.isnan(cos_sim)) - loss = torch.sum(torch.exp(cos_sim), dim=1) - assert not torch.sum(torch.isnan(loss)) - return loss
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/msels/a_model_sel.html b/docs/build/html/_modules/domainlab/algos/msels/a_model_sel.html deleted file mode 100644 index 0ed3852e0..000000000 --- a/docs/build/html/_modules/domainlab/algos/msels/a_model_sel.html +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.msels.a_model_sel — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.msels.a_model_sel

-import abc
-
-
[docs]class AMSel(metaclass=abc.ABCMeta): - def __init__(self): - self.trainer = None - self.tr_obs = None - -
[docs] def accept(self, trainer, tr_obs): - """ - Visitor pattern to trainer - """ - self.trainer = trainer - self.tr_obs = tr_obs
- -
[docs] @abc.abstractmethod - def update(self): - """ - observer + visitor pattern to trainer - """ - raise NotImplementedError
- -
[docs] def if_stop(self): - """ - check if trainer should stop - """ - raise NotImplementedError
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/msels/c_msel.html b/docs/build/html/_modules/domainlab/algos/msels/c_msel.html deleted file mode 100644 index b0956369e..000000000 --- a/docs/build/html/_modules/domainlab/algos/msels/c_msel.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.msels.c_msel — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.msels.c_msel

-"""
-Model Selection should be decoupled from
-"""
-from domainlab.algos.msels.a_model_sel import AMSel
-
-
-
[docs]class MSelTrLoss(AMSel): - """ - 1. Model selection using sum of loss across training domains - 2. Visitor pattern to trainer - """ - def __init__(self, max_es): - self.best_loss = float("inf") - self.es_c = 1 - self.max_es = max_es - super().__init__() - -
[docs] def update(self): - """ - if the best model should be updated - """ - loss = self.trainer.epo_loss_tr # @FIXME - assert loss is not None - flag = True - if loss < self.best_loss: - self.es_c = 1 # restore counter - self.best_loss = loss - else: - self.es_c += 1 - print("early stop counter: ", self.es_c) - flag = False # do not update best model - return flag
- -
[docs] def if_stop(self): - """ - if should early stop - """ - return self.es_c > self.max_es
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/msels/c_msel_oracle.html b/docs/build/html/_modules/domainlab/algos/msels/c_msel_oracle.html deleted file mode 100644 index 48a2c14ce..000000000 --- a/docs/build/html/_modules/domainlab/algos/msels/c_msel_oracle.html +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.msels.c_msel_oracle — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.msels.c_msel_oracle

-"""
-Model Selection should be decoupled from
-"""
-from domainlab.algos.msels.a_model_sel import AMSel
-
-
-
[docs]class MSelOracleVisitor(AMSel): - """ - save best out-of-domain test acc model, but do not affect - how the final model is selected - """ - def __init__(self, msel): - """ - Decorator pattern - """ - super().__init__() - self.best_oracle_acc = 0 - self.msel = msel - -
[docs] def update(self): - """ - if the best model should be updated - """ - self.tr_obs.exp.visitor.save(self.trainer.model, "epoch") - if self.tr_obs.metric_te["acc"] > self.best_oracle_acc: - self.best_oracle_acc = self.tr_obs.metric_te["acc"] # FIXME: only works for classification - self.tr_obs.exp.visitor.save(self.trainer.model, "oracle") - print("oracle model saved") - return self.msel.update()
- -
[docs] def if_stop(self): - """ - if should early stop - oracle model selection does not intervene how models get selected - by the innermost model selection - """ - return self.msel.if_stop()
- -
[docs] def accept(self, trainer, tr_obs): - self.msel.accept(trainer, tr_obs) - super().accept(trainer, tr_obs)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/observers/a_observer.html b/docs/build/html/_modules/domainlab/algos/observers/a_observer.html deleted file mode 100644 index 87537e942..000000000 --- a/docs/build/html/_modules/domainlab/algos/observers/a_observer.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.observers.a_observer — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.observers.a_observer

-"""
-interface for observer + visitor
-"""
-import abc
-
-
-
[docs]class AObVisitor(metaclass=abc.ABCMeta): - """ - Observer + Visitor pattern for model selection - """ -
[docs] @abc.abstractmethod - def update(self, epoch): - """ - return True/False whether the trainer should stop training - """
- -
[docs] @abc.abstractmethod - def accept(self, trainer): - """ - accept invitation as a visitor - """
- -
[docs] @abc.abstractmethod - def after_all(self): - """ - After training is done - """
- -
[docs] @abc.abstractmethod - def clean_up(self): - """ - to be called by a decorator - """
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/observers/b_obvisitor.html b/docs/build/html/_modules/domainlab/algos/observers/b_obvisitor.html deleted file mode 100644 index 99b8edbac..000000000 --- a/docs/build/html/_modules/domainlab/algos/observers/b_obvisitor.html +++ /dev/null @@ -1,407 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.observers.b_obvisitor — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.observers.b_obvisitor

-import os
-import warnings
-
-
-from domainlab.algos.observers.a_observer import AObVisitor
-from domainlab.tasks.task_folder_mk import NodeTaskFolderClassNaMismatch
-from domainlab.tasks.task_pathlist import NodeTaskPathListDummy
-
-
-
[docs]class ObVisitor(AObVisitor): - """ - Observer + Visitor pattern for model selection - """ - def __init__(self, exp, model_sel, device): - """ - observer trainer - """ - self.host_trainer = None - self.exp = exp - self.model_sel = model_sel - self.device = device - self.task = self.exp.task - self.loader_te = self.exp.task.loader_te - self.loader_tr = self.exp.task.loader_tr - self.loader_val = self.exp.task.loader_val - # Note loader_tr behaves/inherit different properties than loader_te - self.epo_te = self.exp.args.epo_te - self.epo = None - self.metric_te = None - self.keep_model = self.exp.args.keep_model - self.perf_metric = None - -
[docs] def update(self, epoch): - print("epoch:", epoch) - self.epo = epoch - if epoch % self.epo_te == 0: - metric_te = self.host_trainer.model.cal_perf_metric( - self.loader_tr, self.device, self.loader_te) - self.metric_te = metric_te - if self.model_sel.update(): - print("model selected") - self.exp.visitor.save(self.host_trainer.model) - print("persisted") - return self.model_sel.if_stop()
- -
[docs] def accept(self, trainer): - """ - accept invitation as a visitor - """ - self.host_trainer = trainer - self.perf_metric = self.host_trainer.model.create_perf_obj(self.task) - self.model_sel.accept(trainer, self)
- -
[docs] def after_all(self): - """ - After training is done - """ - self.exp.visitor.save(self.host_trainer.model, "final") - model_ld = self.exp.visitor.load() - model_ld = model_ld.to(self.device) - model_ld.eval() - print("persisted model performance metric: \n") - metric_te = model_ld.cal_perf_metric(self.loader_tr, self.device, self.loader_te) - self.exp.visitor(metric_te) - flag_task_folder = isinstance(self.exp.task, NodeTaskFolderClassNaMismatch) - flag_task_path_list = isinstance(self.exp.task, NodeTaskPathListDummy) - if flag_task_folder or flag_task_path_list: - fname4model = self.exp.visitor.model_path # pylint: disable=E1101 - file_prefix = os.path.splitext(fname4model)[0] # remove ".csv" - file_name = file_prefix + "_instance_wise_predictions.txt" - self.host_trainer.model.pred2file( - self.loader_te, self.device, - filename=file_name)
- -
[docs] def clean_up(self): - """ - to be called by a decorator - """ - if not self.keep_model: - try: - # oracle means use out-of-domain - # test accuracy to select the model - self.exp.visitor.remove("oracle") # pylint: disable=E1101 - # the last epoch - self.exp.visitor.remove("epoch") # pylint: disable=E1101 - # epoch exist to still have a model to evaluate - # if the training stops in between - self.exp.visitor.remove("final") # pylint: disable=E1101 - self.exp.visitor.remove() # pylint: disable=E1101 - except FileNotFoundError: - warnings.warn("failed to remove model") - try: - self.exp.visitor.remove("ctr") # pylint: disable=E1101 For matchdg - except FileNotFoundError: - pass
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/observers/c_obvisitor_cleanup.html b/docs/build/html/_modules/domainlab/algos/observers/c_obvisitor_cleanup.html deleted file mode 100644 index 43013404c..000000000 --- a/docs/build/html/_modules/domainlab/algos/observers/c_obvisitor_cleanup.html +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.observers.c_obvisitor_cleanup — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.observers.c_obvisitor_cleanup

-from domainlab.algos.observers.a_observer import AObVisitor
-
-
-
[docs]class ObVisitorCleanUp(AObVisitor): - """ - decorator of observer - """ - def __init__(self, observer): - self.observer = observer - -
[docs] def after_all(self): - self.observer.after_all() - self.observer.clean_up()
- -
[docs] def accept(self, trainer): - self.observer.accept(trainer)
- -
[docs] def update(self, epoch): - self.observer.update(epoch)
- -
[docs] def clean_up(self): - self.observer.clean_up()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/observers/c_obvisitor_gen.html b/docs/build/html/_modules/domainlab/algos/observers/c_obvisitor_gen.html deleted file mode 100644 index 76c3185e4..000000000 --- a/docs/build/html/_modules/domainlab/algos/observers/c_obvisitor_gen.html +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.observers.c_obvisitor_gen — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.observers.c_obvisitor_gen

-from domainlab.algos.observers.b_obvisitor import ObVisitor
-from domainlab.utils.flows_gen_img_model import fun_gen
-
-
-
[docs]class ObVisitorGen(ObVisitor): - """ - For Generative Models - """ -
[docs] def after_all(self): - super().after_all() - print("generating images for final model at last epoch") - fun_gen(subfolder_na=self.exp.visitor.model_name+"final", - args=self.exp.args, node=self.exp.task, model=self.host_trainer.model, device=self.device) - - print("generating images for oracle model") - model_or = self.exp.visitor.load("oracle") # @FIXME: name "oracle is a strong dependency - model_or = model_or.to(self.device) - model_or.eval() - fun_gen(subfolder_na=self.exp.visitor.model_name+"oracle", - args=self.exp.args, node=self.exp.task, model=model_or, device=self.device) - print("generating images for selected model") - model_ld = self.exp.visitor.load() - model_ld = model_ld.to(self.device) - model_ld.eval() - fun_gen(subfolder_na=self.exp.visitor.model_name+"selected", - args=self.exp.args, node=self.exp.task, model=model_ld, device=self.device)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/trainers/a_trainer.html b/docs/build/html/_modules/domainlab/algos/trainers/a_trainer.html deleted file mode 100644 index 3858dae5f..000000000 --- a/docs/build/html/_modules/domainlab/algos/trainers/a_trainer.html +++ /dev/null @@ -1,370 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers.a_trainer — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.trainers.a_trainer

-"""
-Base Class for trainer
-"""
-import abc
-
-
-
[docs]class AbstractTrainer(metaclass=abc.ABCMeta): - """ - Algorithm director that controls the data flow - """ - def __init__(self, model, task, observer, device, aconf): - """ - model, task, observer, device, aconf - """ - # @FIXME: aconf and args should be separated - self.model = model - self.task = task - self.observer = observer - self.device = device - self.aconf = aconf - # - self.loader_tr = task.loader_tr - self.loader_te = task.loader_te - self.observer.accept(self) - self.model = self.model.to(device) - # - self.num_batches = len(self.loader_tr) - self.flag_update_hyper_per_epoch = False - self.flag_update_hyper_per_batch = False - self.epo_loss_tr = None - self.hyper_scheduler = None - -
[docs] @abc.abstractmethod - def tr_epoch(self, epoch): - """ - :param epoch: - """ - raise NotImplementedError
- -
[docs] def after_batch(self, epoch, ind_batch): - """ - :param epoch: - :param ind_batch: - """ - return
- -
[docs] @abc.abstractmethod - def before_tr(self): - """ - before training, probe model performance - """ - raise NotImplementedError
- -
[docs] def post_tr(self): - """ - after training - """ - self.observer.after_all()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/trainers/args_dial.html b/docs/build/html/_modules/domainlab/algos/trainers/args_dial.html deleted file mode 100644 index 6bef225e3..000000000 --- a/docs/build/html/_modules/domainlab/algos/trainers/args_dial.html +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers.args_dial — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.trainers.args_dial

-"""
-domain invariant adversarial trainer hyper-parmaeters
-"""
-
-
-
[docs]def add_args2parser_dial(parser): - """ - append hyper-parameters to the main argparser - """ - parser.add_argument('--dial_steps_perturb', type=int, default=3, - help='how many gradient step to go to find an image as adversarials') - parser.add_argument('--dial_noise_scale', type=float, default=0.001, - help='variance of gaussian noise to inject on pure image') - parser.add_argument('--dial_lr', type=float, default=0.003, - help='learning rate to generate adversarial images') - parser.add_argument('--dial_epsilon', type=float, default=0.031, - help='pixel wise threshold to perturb images') - return parser
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/trainers/train_basic.html b/docs/build/html/_modules/domainlab/algos/trainers/train_basic.html deleted file mode 100644 index d09ae354c..000000000 --- a/docs/build/html/_modules/domainlab/algos/trainers/train_basic.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers.train_basic — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.trainers.train_basic

-"""
-basic trainer
-"""
-from torch import optim
-
-from domainlab.algos.trainers.a_trainer import AbstractTrainer
-
-
-
[docs]class TrainerBasic(AbstractTrainer): - """ - basic trainer - """ - def __init__(self, model, task, observer, device, aconf): - super().__init__(model, task, observer, device, aconf) - self.optimizer = optim.Adam(self.model.parameters(), lr=aconf.lr) - -
[docs] def before_tr(self): - """ - check the performance of randomly initialized weight - """ - self.model.evaluate(self.loader_te, self.device)
- -
[docs] def tr_epoch(self, epoch): - self.model.train() - self.epo_loss_tr = 0 - for ind_batch, (tensor_x, vec_y, vec_d, *others) in enumerate(self.loader_tr): - tensor_x, vec_y, vec_d = \ - tensor_x.to(self.device), vec_y.to(self.device), vec_d.to(self.device) - self.optimizer.zero_grad() - loss = self.model.cal_loss(tensor_x, vec_y, vec_d, others) - loss = loss.sum() - loss.backward() - self.optimizer.step() - self.epo_loss_tr += loss.detach().item() - self.after_batch(epoch, ind_batch) - flag_stop = self.observer.update(epoch) # notify observer - return flag_stop
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/trainers/train_dial.html b/docs/build/html/_modules/domainlab/algos/trainers/train_dial.html deleted file mode 100644 index bc3f3e5de..000000000 --- a/docs/build/html/_modules/domainlab/algos/trainers/train_dial.html +++ /dev/null @@ -1,375 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers.train_dial — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.trainers.train_dial

-"""
-use random start to generate adversarial images
-"""
-import torch
-from torch.autograd import Variable
-
-from domainlab.algos.trainers.train_basic import TrainerBasic
-
-
-
[docs]class TrainerDIAL(TrainerBasic): - """ - Trainer Domain Invariant Adversarial Learning - """ -
[docs] def gen_adversarial(self, device, img_natural, vec_y): - """ - use naive trimming to find optimize img in the direction of adversarial gradient, - this is not necessarily constraint optimal due to nonlinearity, - as the constraint epsilon is only considered ad-hoc - """ - # @FIXME: is there better way to initialize adversarial image? - # ensure adversarial image not in computational graph - steps_perturb = self.aconf.dial_steps_perturb - scale = self.aconf.dial_noise_scale - step_size = self.aconf.dial_lr - epsilon = self.aconf.dial_epsilon - img_adv_ini = img_natural.detach() - img_adv_ini = img_adv_ini + scale * torch.randn(img_natural.shape).to(device).detach() - img_adv = img_adv_ini - for _ in range(steps_perturb): - img_adv.requires_grad_() - loss_gen_adv = self.model.cal_loss_gen_adv(img_natural, img_adv, vec_y) - grad = torch.autograd.grad(loss_gen_adv, [img_adv])[0] - # instead of gradient descent, we gradient ascent here - img_adv = img_adv_ini.detach() + step_size * torch.sign(grad.detach()) - img_adv = torch.min(torch.max(img_adv, img_natural - epsilon), img_natural + epsilon) - img_adv = torch.clamp(img_adv, 0.0, 1.0) - return img_adv
- -
[docs] def tr_batch(self, epoch, ind_batch): - """ - anneal parameter for each batch - """ - self.model.hyper_update(epoch*self.num_batches + ind_batch, self.hyper_scheduler) - return super().tr_epoch(epoch)
- -
[docs] def tr_epoch(self, epoch): - self.model.train() - self.epo_loss_tr = 0 - for ind_batch, (tensor_x, vec_y, vec_d, *_) in enumerate(self.loader_tr): - tensor_x, vec_y, vec_d = \ - tensor_x.to(self.device), vec_y.to(self.device), vec_d.to(self.device) - self.optimizer.zero_grad() - loss = self.model.cal_loss(tensor_x, vec_y, vec_d) # @FIXME - tensor_x_adv = self.gen_adversarial(self.device, tensor_x, vec_y) - tensor_x_batch_adv_no_grad = Variable(tensor_x_adv, requires_grad=False) - loss_dial = self.model.cal_loss(tensor_x_batch_adv_no_grad, vec_y, vec_d) # @FIXME - loss = loss.sum() + self.aconf.gamma_reg * loss_dial.sum() - loss.backward() - self.optimizer.step() - self.epo_loss_tr += loss.detach().item() - self.after_batch(epoch, ind_batch) - flag_stop = self.observer.update(epoch) # notify observer - return flag_stop
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/trainers/train_matchdg.html b/docs/build/html/_modules/domainlab/algos/trainers/train_matchdg.html deleted file mode 100644 index 78df1359a..000000000 --- a/docs/build/html/_modules/domainlab/algos/trainers/train_matchdg.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers.train_matchdg — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.trainers.train_matchdg

-from domainlab.algos.compos.matchdg_ctr_erm import MatchCtrErm
-from domainlab.algos.trainers.a_trainer import AbstractTrainer
-
-
-
[docs]class TrainerMatchDG(AbstractTrainer): - def __init__(self, exp, task, ctr_model, model, observer, args, device): - super().__init__(model, task, observer, device, args) - self.exp = exp - self.epo_loss_tr = None - self.ctr_model = ctr_model - self.args = self.aconf - -
[docs] def before_tr(self): - """ - configure trainer accoding to properties of task as well according to algorithm configs - """ - # @FIXME: aconf and args should be separated - # phase 1: contrastive learning - ctr = MatchCtrErm(exp=self.exp, - task=self.task, - phi=self.ctr_model, - args=self.args, - device=self.device, - flag_erm=False) - ctr.train() - print("Phase 1 finished: ", ctr.ctr_mpath) - # phase 2: ERM, initialize object - self.erm = MatchCtrErm(phi=self.model, - exp=self.exp, - task=self.task, - args=self.args, - device=self.device, - flag_erm=True)
- -
[docs] def tr_epoch(self, epoch): - self.model.train() - self.erm.tr_epoch(epoch) - self.epo_loss_tr = self.erm.epo_loss_tr - flag_stop = self.observer.update(epoch) # notify observer - return flag_stop
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/trainers/train_visitor.html b/docs/build/html/_modules/domainlab/algos/trainers/train_visitor.html deleted file mode 100644 index de6792964..000000000 --- a/docs/build/html/_modules/domainlab/algos/trainers/train_visitor.html +++ /dev/null @@ -1,415 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers.train_visitor — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.trainers.train_visitor

-"""
-update hyper-parameters during training
-"""
-import warnings
-import numpy as np
-from domainlab.algos.trainers.train_basic import TrainerBasic
-
-
-
[docs]class TrainerVisitor(TrainerBasic): - """ - TrainerVisitor - """ -
[docs] def set_scheduler(self, scheduler, total_steps, - flag_update_epoch=False, - flag_update_batch=False): - """ - set the warmup or anealing strategy - """ - self.hyper_scheduler = self.model.hyper_init(scheduler) - self.flag_update_hyper_per_epoch = flag_update_epoch - self.flag_update_hyper_per_batch = flag_update_batch - self.hyper_scheduler.set_steps(total_steps=total_steps)
- -
[docs] def after_batch(self, epoch, ind_batch): - if self.flag_update_hyper_per_batch: - self.model.hyper_update(epoch, self.hyper_scheduler) - return super().after_batch(epoch, ind_batch)
- -
[docs] def before_tr(self): - if self.hyper_scheduler is None: - warnings.warn("hyper-parameter scheduler not set, \ - going to use default Warmpup and epoch update") - self.set_scheduler(HyperSchedulerWarmup, - total_steps=self.aconf.warmup, - flag_update_epoch=True)
- -
[docs] def tr_epoch(self, epoch): - """ - update hyper-parameters only per epoch - """ - if self.flag_update_hyper_per_epoch: - self.model.hyper_update(epoch, self.hyper_scheduler) - return super().tr_epoch(epoch)
- -
[docs] def tr_batch(self, epoch, ind_batch): - """ - anneal hyper-parameter for each batch - """ - self.model.hyper_update(epoch*self.num_batches + ind_batch, self.hyper_scheduler) - return super().tr_epoch(epoch)
- - -
[docs]class HyperSchedulerWarmup(): - """ - HyperSchedulerWarmup - """ - def __init__(self, **kwargs): - self.dict_par_setpoint = kwargs - self.total_steps = None - -
[docs] def set_steps(self, total_steps): - """ - set number of total_steps to gradually change optimization parameter - """ - self.total_steps = total_steps
- -
[docs] def warmup(self, par_setpoint, epoch): - """warmup. - start from a small value of par to ramp up the steady state value using - # total_steps - :param epoch: - """ - ratio = ((epoch+1) * 1.) / self.total_steps - list_par = [par_setpoint, par_setpoint * ratio] - par = min(list_par) - return par
- - def __call__(self, epoch): - dict_rst = {} - for key, _ in self.dict_par_setpoint.items(): - dict_rst[key] = self.warmup(self.dict_par_setpoint[key], epoch) - return dict_rst
- - -
[docs]class HyperSchedulerAneal(HyperSchedulerWarmup): - """ - HyperSchedulerAneal - """ -
[docs] def aneal(self, epoch, alpha): - """ - start from a small value of par to ramp up the steady state value using - number of total_steps - :param epoch: - """ - ratio = ((epoch+1) * 1.) / self.total_steps - denominator = (1. + np.exp(-10 * ratio)) - return float((2. / denominator - 1) * alpha)
- - def __call__(self, epoch): - dict_rst = {} - for key, val in self.dict_par_setpoint.items(): - dict_rst[key] = self.aneal(epoch, val) - return dict_rst
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/algos/zoo_algos.html b/docs/build/html/_modules/domainlab/algos/zoo_algos.html deleted file mode 100644 index c48c09414..000000000 --- a/docs/build/html/_modules/domainlab/algos/zoo_algos.html +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.zoo_algos — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.algos.zoo_algos

-from domainlab.algos.builder_dann import NodeAlgoBuilderDANN
-from domainlab.algos.builder_jigen1 import NodeAlgoBuilderJiGen
-from domainlab.algos.builder_deepall import NodeAlgoBuilderDeepAll
-from domainlab.algos.builder_dial import NodeAlgoBuilderDeepAll_DIAL
-from domainlab.algos.builder_diva import NodeAlgoBuilderDIVA
-from domainlab.algos.builder_hduva import NodeAlgoBuilderHDUVA
-from domainlab.algos.builder_matchdg import NodeAlgoBuilderMatchDG
-from domainlab.compos.pcr.request import RequestArgs2ExpCmd
-from domainlab.utils.u_import import import_path
-
-
-
[docs]class AlgoBuilderChainNodeGetter(object): - """ - 1. Hardcoded chain - 3. Return selected node - """ - def __init__(self, args): - self.request = RequestArgs2ExpCmd(args)() - self.args = args - -
[docs] def register_external_node(self, chain): - if self.args.apath is None: - return chain - node_module = import_path(self.args.apath) - node_fun = node_module.get_node_na() # @FIXME: build_node API need - newchain = node_fun(chain) - return newchain
- - def __call__(self): - """ - 1. construct the chain, filter out responsible node, create heavy-weight business object - 2. hard code seems to be the best solution - """ - chain = NodeAlgoBuilderDIVA(None) - chain = NodeAlgoBuilderDeepAll(chain) - chain = NodeAlgoBuilderDeepAll_DIAL(chain) - chain = NodeAlgoBuilderDANN(chain) - chain = NodeAlgoBuilderJiGen(chain) - chain = NodeAlgoBuilderHDUVA(chain) - chain = NodeAlgoBuilderMatchDG(chain) - chain = self.register_external_node(chain) - node = chain.handle(self.request) - return node
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/arg_parser.html b/docs/build/html/_modules/domainlab/arg_parser.html deleted file mode 100644 index 1f9765dc0..000000000 --- a/docs/build/html/_modules/domainlab/arg_parser.html +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.arg_parser — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.arg_parser

-"""
-Command line arguments
-"""
-import argparse
-import warnings
-import yaml
-
-from domainlab.algos.compos.matchdg_args import add_args2parser_matchdg
-from domainlab.algos.trainers.args_dial import add_args2parser_dial
-from domainlab.models.args_vae import add_args2parser_vae
-from domainlab.models.args_jigen import add_args2parser_jigen
-
-
-
[docs]def mk_parser_main(): - """ - Args for command line definition - """ - parser = argparse.ArgumentParser(description='DomainLab') - - parser.add_argument('-c', "--config", default=None, - help="load YAML configuration", dest="config_file", - type=argparse.FileType(mode='r')) - - parser.add_argument('--lr', type=float, default=1e-4, - help='learning rate') - - parser.add_argument('--gamma_reg', type=float, default=0.1, - help='weight of regularization loss') - - parser.add_argument('--es', type=int, default=10, - help='early stop steps') - - parser.add_argument('--seed', type=int, default=0, - help='random seed (default: 0)') - - parser.add_argument('--nocu', action='store_true', default=False, - help='disables CUDA') - - parser.add_argument('--gen', action='store_true', default=False, - help='save generated images') - - parser.add_argument('--keep_model', action='store_true', default=False, - help='do not delete model at the end of training') - - parser.add_argument('--epos', default=2, type=int, - help='maximum number of epochs') - - parser.add_argument('--epo_te', default=1, type=int, - help='test performance per {} epochs') - - parser.add_argument('--debug', action='store_true', default=False) - parser.add_argument('--dmem', action='store_true', default=False) - parser.add_argument('--no_dump', action='store_true', default=False, - help='suppress saving the confusion matrix') - - parser.add_argument('--trainer', type=str, default=None, - help='specify which trainer to use') - - parser.add_argument('--out', type=str, default="zoutput", - help='absolute directory to store outputs') - - parser.add_argument('--dpath', type=str, default="zdpath", - help="path for storing downloaded dataset") - - parser.add_argument('--tpath', type=str, default=None, - help="path for custom task, should implement \ - get_task function") - - parser.add_argument('--npath', type=str, default=None, - help="path of custom neural network for feature \ - extraction") - - parser.add_argument('--npath_dom', type=str, default=None, - help="path of custom neural network for feature \ - extraction") - - parser.add_argument('--npath_argna2val', action='append', - help="specify new arguments and their value \ - e.g. '--npath_argna2val my_custom_arg_na \ - --npath_argna2val xx/yy/zz.py', additional \ - pairs can be appended") - - parser.add_argument('--nname_argna2val', action='append', - help="specify new arguments and their values \ - e.g. '--nname_argna2val my_custom_network_arg_na \ - --nname_argna2val alexnet', additional pairs \ - can be appended") - - parser.add_argument('--nname', type=str, default=None, - help="name of custom neural network for feature \ - extraction of classification") - - parser.add_argument('--nname_dom', type=str, default=None, - help="name of custom neural network for feature \ - extraction of domain") - - parser.add_argument('--apath', type=str, default=None, - help="path for custom AlgorithmBuilder") - - parser.add_argument('--exptag', type=str, default="exptag", - help='tag as prefix of result aggregation file name \ - e.g. git hash for reproducibility') - - parser.add_argument('--aggtag', type=str, default="aggtag", - help='tag in each line of result aggregation file \ - e.g., to specify potential different configurations') - - parser.add_argument('--msel', type=str, default=None, - help='model selection: val, elbo, recon, the \ - elbo and recon only make sense for vae models,\ - will be ignored by other methods') - - parser.add_argument('--aname', metavar="an", type=str, - default=None, - help='algorithm name') - - parser.add_argument('--acon', metavar="ac", type=str, default=None, - help='algorithm configuration name, (default None)') - - parser.add_argument('--task', metavar="ta", type=str, - help='task name') - - arg_group_task = parser.add_argument_group('task args') - - arg_group_task.add_argument('--bs', type=int, default=100, - help='loader batch size for mixed domains') - - arg_group_task.add_argument('--split', type=float, default=0, - help='proportion of training, a value between \ - 0 and 1, 0 means no train-validation split') - - arg_group_task.add_argument('--te_d', nargs='*', default=None, - help='test domain names separated by single space, \ - will be parsed to be list of strings') - - arg_group_task.add_argument('--tr_d', nargs='*', default=None, - help='training domain names separated by \ - single space, will be parsed to be list of \ - strings; if not provided then all available \ - domains that are not assigned to \ - the test set will be used as training domains') - - arg_group_task.add_argument('--san_check', action='store_true', default=False, - help='save images from the dataset as a sanity check') - - arg_group_task.add_argument('--san_num', type=int, default=8, - help='number of images to be dumped for the sanity check') - - # args for variational auto encoder - arg_group_vae = parser.add_argument_group('vae') - arg_group_vae = add_args2parser_vae(arg_group_vae) - arg_group_matchdg = parser.add_argument_group('matchdg') - arg_group_matchdg = add_args2parser_matchdg(arg_group_matchdg) - arg_group_jigen = parser.add_argument_group('jigen') - arg_group_jigen = add_args2parser_jigen(arg_group_jigen) - args_group_dial = parser.add_argument_group('dial') - args_group_dial = add_args2parser_dial(args_group_dial) - return parser
- - -
[docs]def parse_cmd_args(): - """ - get args from command line - """ - parser = mk_parser_main() - args = parser.parse_args() - if args.config_file: - - data = yaml.safe_load(args.config_file) - delattr(args, 'config_file') - arg_dict = args.__dict__ - - for key in data: - if key not in arg_dict: - raise ValueError("The key is not supported: ", key) - - for key, value in data.items(): - if isinstance(value, list): - arg_dict[key].extend(value) - else: - arg_dict[key] = value - - if args.acon is None: - print("\n\n") - warnings.warn("no algorithm conf specified, going to use default") - print("\n\n") - - return args
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/a_nn_builder.html b/docs/build/html/_modules/domainlab/compos/a_nn_builder.html deleted file mode 100644 index 1e0c4d059..000000000 --- a/docs/build/html/_modules/domainlab/compos/a_nn_builder.html +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.a_nn_builder — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.a_nn_builder

-"""
-Integrate Chain-of-Responsibility and Builder Pattern for feature extract
-"""
-
-from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]class AbstractFeatExtractNNBuilderChainNode(AbstractChainNodeHandler): - """ - to ensure chain of responsibility node AbstractChainNodeHandler always - work even some node can not start their heavy weight business object, - avoid override the initializer so that node construction is always - light weight. - """ - def __init__(self, successor_node): - """__init__. - - :param successor_node: - """ - self.net_feat_extract = None - super().__init__(successor_node) - -
[docs] @store_args - def init_business(self, dim_out, args, i_c=None, i_h=None, i_w=None, - flag_pretrain=None, remove_last_layer=False): - """ - initialize **and** return the heavy weight business object for doing - the real job - :param request: subclass can override request object to be string or - function - :return: the constructed service object - """ - return NotImplementedError
- -
[docs] def is_myjob(self, args): - """ - :param args_nname: command line arguments: - "--nname": name of the torchvision model - "--npath": path to the user specified python file with neural - network definition - """ - return NotImplementedError
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/builder_nn_alex.html b/docs/build/html/_modules/domainlab/compos/builder_nn_alex.html deleted file mode 100644 index 4bb8219e4..000000000 --- a/docs/build/html/_modules/domainlab/compos/builder_nn_alex.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.builder_nn_alex — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.builder_nn_alex

-from domainlab.compos.a_nn_builder import AbstractFeatExtractNNBuilderChainNode
-from domainlab.compos.nn_zoo.nn_alex import Alex4DeepAll, AlexNetNoLastLayer
-
-
-
[docs]def mkNodeFeatExtractNNBuilderNameAlex(arg_name4net, arg_val): - class NodeFeatExtractNNBuilderAlex(AbstractFeatExtractNNBuilderChainNode): - """NodeFeatExtractNNBuilderAlex. - Uniform interface to return AlexNet and other neural network as feature - extractor from torchvision or external python file""" - def init_business(self, dim_out, args, i_c=None, i_h=None, i_w=None, - remove_last_layer=False, flag_pretrain=True): - """ - initialize **and** return the heavy weight business - object for doing the real job - :param request: subclass can override request object - to be string or function - :return: the constructed service object - """ - if not remove_last_layer: - self.net_feat_extract = Alex4DeepAll(flag_pretrain, dim_out) - else: - self.net_feat_extract = AlexNetNoLastLayer(flag_pretrain) - return self.net_feat_extract - - def is_myjob(self, args): - """is_myjob. - :param args: command line arguments: - "--nname": name of the torchvision model - """ - arg_name = getattr(args, arg_name4net) - return arg_name == arg_val - return NodeFeatExtractNNBuilderAlex
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/builder_nn_conv_bn_relu_2.html b/docs/build/html/_modules/domainlab/compos/builder_nn_conv_bn_relu_2.html deleted file mode 100644 index b2f06df5f..000000000 --- a/docs/build/html/_modules/domainlab/compos/builder_nn_conv_bn_relu_2.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.builder_nn_conv_bn_relu_2 — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.builder_nn_conv_bn_relu_2

-from domainlab.compos.a_nn_builder import AbstractFeatExtractNNBuilderChainNode
-from domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 import NetConvBnReluPool2L
-
-
-
[docs]def mkNodeFeatExtractNNBuilderNameConvBnRelu2(arg_name4net, arg_val, - conv_stride): - """mkNodeFeatExtractNNBuilderNameConvBnRelu2. - In chain of responsibility selection of neural network, reuse code to add - more possibilities of neural network of the same family. - :param arg_name4net: name of nn in args - :param arg_val: the registered name of the neural network to be added - :param conv_stride: should be 1 for 28*28 images - :param i_c: - :param i_h: - :param i_w: - """ - class _NodeFeatExtractNNBuilderConvBnRelu2L( - AbstractFeatExtractNNBuilderChainNode): - """NodeFeatExtractNNBuilderConvBnRelu2L.""" - - def init_business(self, dim_out, args, i_c, i_h, i_w, - flag_pretrain=None, remove_last_layer=False): - """ - :param flag_pretrain - """ - self.net_feat_extract = NetConvBnReluPool2L( - i_c=i_c, i_h=i_h, i_w=i_w, - conv_stride=conv_stride, dim_out_h=dim_out) - return self.net_feat_extract - - def is_myjob(self, args): - """is_myjob. - :param args: command line arguments: - "--nname": name of the torchvision model - """ - arg_name = getattr(args, arg_name4net) - return arg_name == arg_val - return _NodeFeatExtractNNBuilderConvBnRelu2L
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/builder_nn_external_from_file.html b/docs/build/html/_modules/domainlab/compos/builder_nn_external_from_file.html deleted file mode 100644 index 60eeb591a..000000000 --- a/docs/build/html/_modules/domainlab/compos/builder_nn_external_from_file.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.builder_nn_external_from_file — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.builder_nn_external_from_file

-from domainlab.compos.a_nn_builder import AbstractFeatExtractNNBuilderChainNode
-from domainlab.utils.u_import_net_module import \
-    build_external_obj_net_module_feat_extract
-
-
-
[docs]def mkNodeFeatExtractNNBuilderExternFromFile(arg_name_net_path): - """ - for each algorithm, there might exist different feature extractors, e.g. - for diva, there can be class feature extractor and domain feature - extractor - """ - class _LNodeFeatExtractNNBuilderExternFromFile( - AbstractFeatExtractNNBuilderChainNode): - """LNodeFeatExtractNNBuilderExternFromFile. - Local class to return - """ - def init_business(self, dim_out, args, flag_pretrain, - remove_last_layer, - i_c=None, i_h=None, i_w=None): - """ - initialize **and** return the heavy weight business object for - doing the real job - :param request: subclass can override request object to be - string or function - :return: the constructed service object - """ - pyfile4net = getattr(args, arg_name_net_path) - net = build_external_obj_net_module_feat_extract( - pyfile4net, dim_out, remove_last_layer) - return net - - def is_myjob(self, args): - """is_myjob. - """ - pyfile4net = getattr(args, arg_name_net_path) - return pyfile4net is not None - return _LNodeFeatExtractNNBuilderExternFromFile
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_adversarial.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/net_adversarial.html deleted file mode 100644 index 48dccbc11..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_adversarial.html +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.net_adversarial — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.net_adversarial

-from torch import nn
-from torch.autograd import Function
-
-
-
[docs]class Flatten(nn.Module): -
[docs] def forward(self, x): - x = x.view(x.size()[0], -1) - return x
- - -
[docs]class AutoGradFunReverseMultiply(Function): - """ - https://pytorch.org/docs/stable/autograd.html - https://pytorch.org/docs/stable/notes/extending.html#extending-autograd - """ -
[docs] @staticmethod - def forward(ctx, x, alpha): - ctx.alpha = alpha - return x.view_as(x)
- -
[docs] @staticmethod - def backward(ctx, grad_output): - output = grad_output.neg() * ctx.alpha - return output, None
- - -
[docs]class AutoGradFunMultiply(Function): -
[docs] @staticmethod - def forward(ctx, x, alpha): - ctx.alpha = alpha - return x.view_as(x)
- -
[docs] @staticmethod - def backward(ctx, grad_output): - output = grad_output * ctx.alpha - return output, None
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_classif.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/net_classif.html deleted file mode 100644 index 5c2e9e90e..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_classif.html +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.net_classif — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.net_classif

-"Classifier"
-import torch
-import torch.nn as nn
-from torch.nn import functional as F
-
-
-
[docs]class ClassifDropoutReluLinear(nn.Module): - """first apply dropout, then relu, then linearly fully connected, without activation""" - def __init__(self, z_dim, target_dim): - """ - :param z_dim: - :param target_dim: - """ - super().__init__() - self.op_drop = nn.Dropout() - self.op_linear = nn.Linear(z_dim, target_dim) - torch.nn.init.xavier_uniform_(self.op_linear.weight) - self.op_linear.bias.data.zero_() - -
[docs] def forward(self, z_vec): - """ - :param z_vec: - """ - hidden = F.relu(self.op_drop(z_vec)) - logit = self.op_linear(hidden) - return logit
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.html deleted file mode 100644 index 5832a664d..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.html +++ /dev/null @@ -1,395 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2

-"""
-In PyTorch, images are represented as [channels, height, width]
-"""
-import torch
-import torch.nn as nn
-
-from domainlab.compos.nn_zoo.nn import DenseNet
-from domainlab.compos.utils_conv_get_flat_dim import get_flat_dim
-
-
-
[docs]def mk_conv_bn_relu_pool(i_channel, conv_stride=1, max_pool_stride=2): - """ - Convolution, batch norm, maxpool_2d - Convolution with maxpool_2d as last operation - :param i_channel: - :param conv_stride: - :param max_pool_stride: - """ - conv_net = nn.Sequential( - nn.Conv2d(i_channel, 32, kernel_size=5, - stride=conv_stride, bias=False), - nn.BatchNorm2d(32), - nn.ReLU(), - nn.MaxPool2d(2, stride=max_pool_stride), - nn.Conv2d(32, 64, kernel_size=5, stride=conv_stride, bias=False), - nn.BatchNorm2d(64), - nn.ReLU(), - nn.MaxPool2d(2, stride=max_pool_stride), - ) - torch.nn.init.xavier_uniform_(conv_net[0].weight) - torch.nn.init.xavier_uniform_(conv_net[4].weight) - return conv_net
- - -
[docs]class NetConvBnReluPool2L(nn.Module): - def __init__(self, i_c, i_h, i_w, conv_stride, dim_out_h): - """ - :param dim_out_h: - """ - super().__init__() - self.conv_net = mk_conv_bn_relu_pool(i_c, conv_stride) - ### - self.hdim = get_flat_dim(self.conv_net, i_c, i_h, i_w) - self.layer_last = nn.Linear(self.hdim, dim_out_h) - -
[docs] def forward(self, tensor_x): - """ - :param tensor_x: image - """ - conv_out = self.conv_net(tensor_x) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) - flat = conv_out.view(-1, self.hdim) # 1024 = 64 * (4*4) - hidden = self.layer_last(flat) - return hidden
- - -
[docs]class NetConvDense(nn.Module): - """ - - For direct topic inference - - For custom deep_all, which is extracting the path of VAE from encoder - until classifier. note in encoder, there is extra layer of hidden to mean - and scale, in this component, it is replaced with another hidden layer. - """ - def __init__(self, i_c, i_h, i_w, conv_stride, dim_out_h, args, dense_layer=None): - """ - :param dim_out_h: - """ - super().__init__() - self.conv_net = mk_conv_bn_relu_pool(i_c, conv_stride) - ### - self.hdim = get_flat_dim(self.conv_net, i_c, i_h, i_w) - if dense_layer is None: - self.dense_layers = DenseNet(self.hdim, out_hidden_size=dim_out_h) - else: - self.dense_layers = dense_layer - -
[docs] def forward(self, tensor_x): - """ - :param tensor_x: image - """ - conv_out = self.conv_net(tensor_x) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) - flat = conv_out.view(-1, self.hdim) # 1024 = 64 * (4*4) - hidden = self.dense_layers(flat) - return hidden
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_gated.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/net_gated.html deleted file mode 100644 index d8387d510..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/net_gated.html +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.net_gated — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.net_gated

-import torch.nn as nn
-
-
-
[docs]class GatedDense(nn.Module): - def __init__(self, input_size, output_size, activation=None): - super(GatedDense, self).__init__() - - self.activation = activation - self.sigmoid = nn.Sigmoid() - self.h = nn.Linear(input_size, output_size) - self.g = nn.Linear(input_size, output_size) - -
[docs] def forward(self, x): - h = self.h(x) - if self.activation is not None: - h = self.activation(self.h(x)) - - g = self.sigmoid(self.g(x)) - - return h * g
- -#========================================================================== -
[docs]class GatedConv2d(nn.Module): - def __init__(self, input_channels, output_channels, kernel_size, stride, padding, dilation=1, activation=None): - super(GatedConv2d, self).__init__() - - self.activation = activation - self.sigmoid = nn.Sigmoid() - - self.h = nn.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation) - self.g = nn.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation) - -
[docs] def forward(self, x): - if self.activation is None: - h = self.h(x) - else: - h = self.activation( self.h( x ) ) - - g = self.sigmoid( self.g( x ) ) - - return h * g
- -#============================================================================== -
[docs]class Conv2d(nn.Module): - def __init__(self, input_channels, output_channels, kernel_size, stride, padding, dilation=1, activation=None, bias=True): - super(Conv2d, self).__init__() - - self.activation = activation - self.conv = nn.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation, bias=bias) - -
[docs] def forward(self, x): - h = self.conv(x) - if self.activation is None: - out = h - else: - out = self.activation(h) - return out
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/nn.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/nn.html deleted file mode 100644 index 7524d4c60..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/nn.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.nn — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.nn

-import torch.nn as nn
-
-
-
[docs]class LayerId(nn.Module): - """ - used to delete layers - """ - def __init__(self): - super().__init__() - -
[docs] def forward(self, x): - """ - :param x: - """ - return x
- - -
[docs]class DenseNet(nn.Module): - """ - (input)-dropout-linear-relu-dropout-linear-relu(output) - """ - def __init__(self, input_flat_size, out_hidden_size=1024, last_feat_dim=4096, p_dropout=0.5): - """ - :param input_flat_size: - :param out_hidden_size: - :param last_feat_dim: - """ - super().__init__() - self.h_layers = nn.Sequential( - nn.Dropout(p=p_dropout), - nn.Linear(input_flat_size, last_feat_dim), - nn.ReLU(inplace=True), - nn.Dropout(p=p_dropout), - nn.Linear(last_feat_dim, out_hidden_size), - nn.ReLU(inplace=True), - ) - -
[docs] def forward(self, tensor_x): - """ - :param x: - """ - flat = tensor_x.view(tensor_x.shape[0], -1) - out = self.h_layers(flat) - return out
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/nn_alex.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/nn_alex.html deleted file mode 100644 index 7e886cd44..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/nn_alex.html +++ /dev/null @@ -1,378 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.nn_alex — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.nn_alex

-import torch.nn as nn
-from torchvision import models as torchvisionmodels
-
-from domainlab.compos.nn_zoo.nn import LayerId
-from domainlab.compos.nn_zoo.nn_torchvision import NetTorchVisionBase
-
-
-
[docs]class AlexNetBase(NetTorchVisionBase): - """ - .. code-block:: python - - AlexNet( - (features): Sequential( - (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2)) - (1): ReLU(inplace=True) - (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) - (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) - (4): ReLU(inplace=True) - (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) - (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) - (7): ReLU(inplace=True) - (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) - (9): ReLU(inplace=True) - (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) - (11): ReLU(inplace=True) - (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) - ) - (avgpool): AdaptiveAvgPool2d(output_size=(6, 6)) - (classifier): Sequential( - (0): Dropout(p=0.5, inplace=False) - (1): Linear(in_features=9216, out_features=4096, bias=True) - (2): ReLU(inplace=True) - (3): Dropout(p=0.5, inplace=False) - (4): Linear(in_features=4096, out_features=4096, bias=True) - (5): ReLU(inplace=True) - (6): Linear(in_features=4096, out_features=7, bias=True) - ) - ) - """ -
[docs] def fetch_net(self, flag_pretrain): - self.net_torchvision = torchvisionmodels.alexnet( - pretrained=flag_pretrain)
- - -
[docs]class Alex4DeepAll(AlexNetBase): - """ - change the last layer output of AlexNet to the dimension of the - """ - def __init__(self, flag_pretrain, dim_y): - super().__init__(flag_pretrain) - if self.net_torchvision.classifier[6].out_features != dim_y: - print("original alex net out dim", self.net_torchvision.classifier[6].out_features) - num_ftrs = self.net_torchvision.classifier[6].in_features - self.net_torchvision.classifier[6] = nn.Linear(num_ftrs, dim_y) - print("re-initialized to ", dim_y)
- - -
[docs]class AlexNetNoLastLayer(AlexNetBase): - """ - Change the last layer of AlexNet with identity layer, - the classifier from VAE can then have the same layer depth as deep_all - model so it is fair for comparison - """ - def __init__(self, flag_pretrain): - super().__init__(flag_pretrain) - self.net_torchvision.classifier[6] = LayerId()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/nn_zoo/nn_torchvision.html b/docs/build/html/_modules/domainlab/compos/nn_zoo/nn_torchvision.html deleted file mode 100644 index 0380a13b2..000000000 --- a/docs/build/html/_modules/domainlab/compos/nn_zoo/nn_torchvision.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo.nn_torchvision — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.nn_zoo.nn_torchvision

-import torch.nn as nn
-
-
-
[docs]class NetTorchVisionBase(nn.Module): - """ - fetch model from torchvision - """ - def __init__(self, flag_pretrain): - super().__init__() - self.net_torchvision = None - self.fetch_net(flag_pretrain) - -
[docs] def fetch_net(self, flag_pretrain): - raise NotImplementedError
- -
[docs] def forward(self, tensor): - """ - delegate forward operation to self.net_torchvision - """ - out = self.net_torchvision(tensor) - return out
- -
[docs] def show(self): - """ - print out which layer will be optimized - """ - for name, param in self.net_torchvision.named_parameters(): - if param.requires_grad: - print("layers that will be optimized: \t", name)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/utils_conv_get_flat_dim.html b/docs/build/html/_modules/domainlab/compos/utils_conv_get_flat_dim.html deleted file mode 100644 index 897f55b2f..000000000 --- a/docs/build/html/_modules/domainlab/compos/utils_conv_get_flat_dim.html +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.utils_conv_get_flat_dim — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.utils_conv_get_flat_dim

-import torch
-
-
-
[docs]def get_flat_dim(module, i_channel, i_h, i_w, batchsize=5): - """flat the convolution layer output and get the flat dimension for fully - connected network - :param module: - :param i_channel: - :param i_h: - :param i_w: - :param batchsize: - """ - img = torch.randn(i_channel, i_h, i_w) - img3 = img.repeat(batchsize, 1, 1, 1) # create batchsize repitition - conv_output = module(img3) - if len(conv_output.shape) == 2: - flat_dim = conv_output.shape[1] - else: - flat_dim = conv_output.shape[1] * conv_output.shape[2] * conv_output.shape[3] - return flat_dim
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/compos/zoo_nn.html b/docs/build/html/_modules/domainlab/compos/zoo_nn.html deleted file mode 100644 index f1dcd8ed2..000000000 --- a/docs/build/html/_modules/domainlab/compos/zoo_nn.html +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.zoo_nn — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.compos.zoo_nn

-import copy
-
-from domainlab.compos.builder_nn_alex import mkNodeFeatExtractNNBuilderNameAlex
-from domainlab.compos.builder_nn_conv_bn_relu_2 import \
-    mkNodeFeatExtractNNBuilderNameConvBnRelu2
-from domainlab.compos.builder_nn_external_from_file import \
-    mkNodeFeatExtractNNBuilderExternFromFile
-
-
-
[docs]class FeatExtractNNBuilderChainNodeGetter(object): - """ - 1. Hardcoded chain - 3. Return selected node - """ - def __init__(self, args, arg_name_of_net, - arg_path_of_net): - """__init__. - :param args: command line arguments - :param arg_name_of_net: args.npath to specify - where to get the external architecture for example - """ - self.request = args - self.arg_name_of_net = arg_name_of_net - self.arg_path_of_net = arg_path_of_net - - def __call__(self): - """ - 1. construct the chain, filter out responsible node, - create heavy-weight business object - 2. hard code seems to be the best solution - """ - chain = mkNodeFeatExtractNNBuilderNameConvBnRelu2( - self.arg_name_of_net, - arg_val="conv_bn_pool_2", conv_stride=1)(None) - chain = mkNodeFeatExtractNNBuilderNameConvBnRelu2( - arg_name4net="nname_dom", - arg_val="conv_bn_pool_2", conv_stride=1)(chain) - chain = mkNodeFeatExtractNNBuilderNameAlex( - self.arg_name_of_net, "alexnet")(chain) - chain = mkNodeFeatExtractNNBuilderExternFromFile( - self.arg_path_of_net)(chain) - node = chain.handle(self.request) - return node
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/a_dset_mnist_color_rgb_solo.html b/docs/build/html/_modules/domainlab/dsets/a_dset_mnist_color_rgb_solo.html deleted file mode 100644 index 8d75e0349..000000000 --- a/docs/build/html/_modules/domainlab/dsets/a_dset_mnist_color_rgb_solo.html +++ /dev/null @@ -1,473 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.a_dset_mnist_color_rgb_solo — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.a_dset_mnist_color_rgb_solo

-"""
-Color MNIST with single color
-"""
-import abc
-import os
-import struct
-
-import numpy as np
-from PIL import Image
-from torch.utils.data import Dataset
-from torchvision import datasets, transforms
-
-from domainlab.dsets.utils_data import mk_fun_label2onehot
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]class ADsetMNISTColorRGBSolo(Dataset, metaclass=abc.ABCMeta): - """ - Color MNIST with single color - 1. nominal domains: color palettes/range/spectrum - 2. subdomains: color(foreground, background) - 3. structure: each subdomain contains a combination of - foreground+background color - """ -
[docs] @abc.abstractmethod - def get_foreground_color(self, ind): - raise NotImplementedError
- -
[docs] @abc.abstractmethod - def get_background_color(self, ind): - raise NotImplementedError
- -
[docs] @abc.abstractmethod - def get_num_colors(self): - raise NotImplementedError
- - @store_args - def __init__(self, ind_color, path, - subset_step=100, - color_scheme="both", - label_transform=mk_fun_label2onehot(10), - list_transforms=None, - raw_split='train', - flag_rand_color=False, - ): - """ - :param ind_color: index of a color palette - :param path: disk storage directory - :param color_scheme: - num(paint according to number), - back(only paint background) - both (background and foreground) - :param list_transforms: torch transformations - :param raw_split: default use the training part of mnist - :param flag_rand_color: flag if to randomly paint each image - (depreciated) - :param label_transform: e.g. index to one hot vector - """ - dpath = os.path.normpath(path) - flag_train = True - if raw_split!="train": - flag_train = False - dataset = datasets.MNIST(root=dpath, - train=flag_train, - download=True, - transform=transforms.ToTensor()) - - if color_scheme not in ['num', 'back', 'both']: - raise ValueError("color must be either 'num', 'back' or 'both") - raw_path = os.path.dirname(dataset.raw_folder) - self._collect_imgs_labels(raw_path, raw_split) - inds_subset = list(range(0, len(dataset), subset_step)) - self.images = self.images[inds_subset, ::] - self.labels = self.labels[inds_subset] - self._color_imgs_onehot_labels() - - def _collect_imgs_labels(self, path, raw_split): - """ - :param path: - :param raw_split: - """ - if raw_split == 'train': - fimages = os.path.join(path, 'raw', 'train-images-idx3-ubyte') - flabels = os.path.join(path, 'raw', 'train-labels-idx1-ubyte') - else: - fimages = os.path.join(path, 'raw', 't10k-images-idx3-ubyte') - flabels = os.path.join(path, 'raw', 't10k-labels-idx1-ubyte') - - # Load images - with open(fimages, 'rb') as f_h: - _, _, rows, cols = struct.unpack(">IIII", f_h.read(16)) - self.images = np.fromfile(f_h, dtype=np.uint8).reshape( - -1, rows, cols) - - # Load labels - with open(flabels, 'rb') as f_h: - struct.unpack(">II", f_h.read(8)) - self.labels = np.fromfile(f_h, dtype=np.int8) - self.images = np.tile(self.images[:, :, :, np.newaxis], 3) - - def __len__(self): - return len(self.images) - - def _op_color_img(self, image): - """ - transforms raw image into colored version - """ - # randomcolor is a flag orthogonal to num-back-both - if self.flag_rand_color: - - c_f = self.get_foreground_color(np.random.randint(0, self.get_num_colors())) - c_b = 0 - if self.color_scheme == 'both': - count = 0 - while True: - c_b = self.get_background_color(np.random.randint(0, self.get_num_colors())) - if c_b != c_f and count < 10: - # exit loop if background color - # is not equal to foreground - break - else: - if self.color_scheme == 'num': - # domain and class label has perfect mutual information: - # assign color - # according to their class (0,10) - c_f = self.get_foreground_color(self.ind_color) - c_b = np.array([0]*3) - elif self.color_scheme == 'back': # only paint background - c_f = np.array([0]*3) - c_b = self.get_background_color(self.ind_color) - - else: # paint both background and foreground - c_f = self.get_foreground_color(self.ind_color) - c_b = self.get_background_color(self.ind_color) - image[:, :, 0] = image[:, :, 0] / 255 * c_f[0] + \ - (255 - image[:, :, 0]) / 255 * c_b[0] - image[:, :, 1] = image[:, :, 1] / 255 * c_f[1] + \ - (255 - image[:, :, 1]) / 255 * c_b[1] - image[:, :, 2] = image[:, :, 2] / 255 * c_f[2] + \ - (255 - image[:, :, 2]) / 255 * c_b[2] - return image - - def _color_imgs_onehot_labels(self): - """ - finish all time consuming operations before torch.dataset.__getitem__ - """ - for i in range(self.images.shape[0]): # 60k*28*28*3 - img = self.images[i] # size: 28*28*3 instead of 3*28*28 - self.images[i] = self._op_color_img(img) - - def __getitem__(self, idx): - image = self.images[idx] # range of pixel: [0,255] - label = self.labels[idx] - if self.label_transform is not None: - label = self.label_transform(label) - image = Image.fromarray(image) # numpy array 28*28*3 -> 3*28*28 - if self.list_transforms is not None: - for trans in self.list_transforms: - image = trans(image) - image = transforms.ToTensor()(image) # range of pixel [0,1] - return image, label
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/dset_img_path_list.html b/docs/build/html/_modules/domainlab/dsets/dset_img_path_list.html deleted file mode 100644 index aa075007a..000000000 --- a/docs/build/html/_modules/domainlab/dsets/dset_img_path_list.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.dset_img_path_list — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.dset_img_path_list

-import os
-
-import torch.utils.data as data
-
-from domainlab.dsets.utils_data import fun_img_path_loader_default
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]class DsetImPathList(data.Dataset): - @store_args - def __init__(self, root_img, path2filelist, trans_img=None, trans_target=None): - """ - one file provide image path and label which forms a domain - """ - self.list_tuple_img_label = [] - self.get_list_tuple_img_label() - -
[docs] def get_list_tuple_img_label(self): - with open(self.path2filelist, 'r') as f_h: - for str_line in f_h.readlines(): - path_img, label_img = str_line.strip().split() - self.list_tuple_img_label.append((path_img, int(label_img))) # @FIXME: string to int, not necessarily continuous
- - def __getitem__(self, index): - path_img, target = self.list_tuple_img_label[index] - target = target - 1 # @FIXME: make this more general - img = fun_img_path_loader_default(os.path.join(self.root_img, path_img)) - if self.trans_img is not None: - img = self.trans_img(img) - if self.trans_target is not None: - target = self.trans_target(target) - return img, target, path_img - - def __len__(self): - return len(self.list_tuple_img_label)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/dset_mnist_color_solo_default.html b/docs/build/html/_modules/domainlab/dsets/dset_mnist_color_solo_default.html deleted file mode 100644 index 1ef791b6e..000000000 --- a/docs/build/html/_modules/domainlab/dsets/dset_mnist_color_solo_default.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.dset_mnist_color_solo_default — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.dset_mnist_color_solo_default

-from domainlab.dsets.a_dset_mnist_color_rgb_solo import ADsetMNISTColorRGBSolo
-from domainlab.dsets.utils_color_palette import default_rgb_palette
-
-
-
[docs]class DsetMNISTColorSoloDefault(ADsetMNISTColorRGBSolo): - @property - def palette(self): - return default_rgb_palette - -
[docs] def get_num_colors(self): - return len(self.palette)
- -
[docs] def get_background_color(self, ind): - if self.color_scheme == 'back': - return self.palette[ind] - if self.color_scheme == 'both': - return self.palette[-(ind-3)] - # only array can be multiplied with number 255 directly - return self.palette[ind]
- # "num" do not use background at all - -
[docs] def get_foreground_color(self, ind): - if self.color_scheme == "num": - return self.palette[-(ind + 1)] - return self.palette[ind]
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/dset_poly_domains_mnist_color_default.html b/docs/build/html/_modules/domainlab/dsets/dset_poly_domains_mnist_color_default.html deleted file mode 100644 index ea6a666fb..000000000 --- a/docs/build/html/_modules/domainlab/dsets/dset_poly_domains_mnist_color_default.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.dset_poly_domains_mnist_color_default — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.dset_poly_domains_mnist_color_default

-"""
-merge several solo-color mnist to form a mixed dataset
-"""
-import numpy as np
-from torch.utils.data import Dataset
-
-from domainlab.dsets.dset_mnist_color_solo_default import \
-    DsetMNISTColorSoloDefault
-from domainlab.dsets.utils_data import mk_fun_label2onehot
-
-
-
[docs]class DsetMNISTColorMix(Dataset): - """ - merge several solo-color mnist to form a mixed dataset - """ - def __init__(self, n_domains, path, color_scheme='both'): - self.n_domains = n_domains - self.list_dset = [None] * n_domains - self.fun_dlabel2onehot = mk_fun_label2onehot(n_domains) - for domain_ind in range(n_domains): - self.list_dset[domain_ind] = \ - DsetMNISTColorSoloDefault(domain_ind, path, - color_scheme=color_scheme) - self.list_len = [len(ds) for ds in self.list_dset] - self.size_single = min(self.list_len) - - def __len__(self): - """__len__.""" - return sum(self.list_len) - - def __getitem__(self, idx): - rand_domain = np.random.random_integers(self.n_domains-1) # @FIXME - idx_local = idx % self.size_single - img, c_label = self.list_dset[rand_domain][idx_local] - return img, c_label, self.fun_dlabel2onehot(rand_domain)
- - -
[docs]class DsetMNISTColorMixNoDomainLabel(DsetMNISTColorMix): - """ - DsetMNISTColorMixNoDomainLabel - """ - def __getitem__(self, idx): - img, c_label, _ = super().__getitem__(idx) - return img, c_label
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/dset_subfolder.html b/docs/build/html/_modules/domainlab/dsets/dset_subfolder.html deleted file mode 100644 index 27f3cfe1f..000000000 --- a/docs/build/html/_modules/domainlab/dsets/dset_subfolder.html +++ /dev/null @@ -1,445 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.dset_subfolder — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.dset_subfolder

-"""
-https://github.com/pytorch/vision/blob/bb5af1d77658133af8be8c9b1a13139722315c3a/torchvision/datasets/folder.py#L93
-https://pytorch.org/vision/stable/_modules/torchvision/datasets/folder.html#DatasetFolder.fetch_img_paths
-"""
-import os
-import sys
-import warnings
-from typing import Any, Tuple
-
-from torchvision.datasets import DatasetFolder
-from rich import print as rprint
-
-
[docs]def has_file_allowed_extension(filename: str, extensions: Tuple[str, ...]) -> bool: - """ - Checks if a file is an allowed extension. - Args: - filename (string): path to a file - extensions (tuple of strings): extensions to consider (lowercase) - Returns: bool: True if the filename ends with one of given extensions - """ - return filename.lower().endswith(extensions)
- - -
[docs]def fetch_img_paths(path_dir, class_to_idx, extensions=None, is_valid_file=None): - """ - :param path_dir: path to fetch images in string format - :param class_to_idx: given list of strings as class names - {classes[i]: i for i in range(len(classes))} - :param extensions: file extensions in fstring format - :param is_valid_file: user provided function to check if the file is valid or not - :return : list_tuple_path_cls_ind: list of tuple, (path of file, class index) - """ - list_tuple_path_cls_ind = [] - path_dir = os.path.expanduser(path_dir) - # since this function is only called by the class below, which now ensures that - # extensions xor is_valid_file is not None, this check cannot be triggered - # if not ((extensions is None) ^ (is_valid_file is None)): - # raise ValueError( - # "Both extensions and is_valid_file cannot be None or not None at the same time") - if extensions is not None: - def functor_is_valid_file(filena): - return has_file_allowed_extension(filena, extensions) - is_valid_file = functor_is_valid_file - for target in sorted(class_to_idx.keys()): - apath = os.path.join(path_dir, target) - if not os.path.isdir(apath): - continue - for root, _, fnames in sorted(os.walk(apath, followlinks=True)): - for fname in sorted(fnames): - path_file = os.path.join(root, fname) - if is_valid_file(path_file): - item = (path_file, class_to_idx[target]) - list_tuple_path_cls_ind.append(item) # @FIXME - return list_tuple_path_cls_ind
- - -
[docs]class DsetSubFolder(DatasetFolder): - """ - Only use user provided class names, ignore the other subfolders - :param list_class_dir: list of class directories to use as classes - """ - def __init__(self, root, loader, list_class_dir, extensions=None, transform=None, - target_transform=None, is_valid_file=None): - self.list_class_dir = list_class_dir - - if is_valid_file is not None and extensions is not None: - raise ValueError( - "Both extensions and is_valid_file cannot be not None at the same time") - - if is_valid_file is None and extensions is None: - # setting default extensions - extensions = ('jpg', 'jpeg', 'png') - warnings.warn("no user provided extensions, set to be jpg, jpeg, png") - - super().__init__(root, - loader, - extensions=extensions, - transform=transform, - target_transform=target_transform, - is_valid_file=is_valid_file) - classes, class_to_idx = self._find_classes(self.root) - samples = fetch_img_paths(self.root, class_to_idx, extensions, is_valid_file) - self.classes = classes - self.class_to_idx = class_to_idx - self.samples = samples - self.targets = [s[1] for s in samples] - self.path2imgs = [s[0] for s in samples] - - def __getitem__(self, index: int) -> Tuple[Any, Any]: - """ - Args: - index (int): Index - - Returns: - tuple: (sample, target) where target is class_index of the target class. - """ - path, target = self.samples[index] - sample = self.loader(path) - if self.transform is not None: - sample = self.transform(sample) - if self.target_transform is not None: - target = self.target_transform(target) - - return sample, target, (path,) - - def _find_classes(self, mdir): - """ - Finds the class folders in a dataset. - Args: - mdir (string): Root mdirectory path. - Returns: - tuple: (classes, class_to_idx) where classes are relative to (mdir), - and class_to_idx is a dictionary. - Ensures: - No class is a submdirectory of another. - """ - if sys.version_info >= (3, 5): - # Faster and available in Python 3.5 and above - list_subfolders = [subfolder.name for subfolder in list(os.scandir(mdir))] - rprint("list of subfolders", list_subfolders) - classes = [d.name for d in os.scandir(mdir) \ - if d.is_dir() and d.name in self.list_class_dir] - else: - classes = [d for d in os.listdir(mdir) \ - if os.path.isdir(os.path.join(mdir, d)) and d in self.list_class_dir] - flag_user_input_classes_in_folder = (set(self.list_class_dir) <= set(classes)) - if not flag_user_input_classes_in_folder: - print("user provided class names:", self.list_class_dir) - print("subfolder names from folder:", mdir, classes) - raise RuntimeError("user provided class names does not match the subfolder names") - classes.sort() - class_to_idx = {classes[i]: i for i in range(len(classes))} - return classes, class_to_idx
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/utils_data.html b/docs/build/html/_modules/domainlab/dsets/utils_data.html deleted file mode 100644 index dd9ed6737..000000000 --- a/docs/build/html/_modules/domainlab/dsets/utils_data.html +++ /dev/null @@ -1,403 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.utils_data — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.utils_data

-"""
-Utilities for dataset
-"""
-import datetime
-
-import torch
-import torch.utils.data as data_utils
-from PIL import Image
-from torch.utils.data import Dataset
-from torchvision.utils import save_image
-
-
-
[docs]def fun_img_path_loader_default(path): - """ - https://discuss.pytorch.org/t/handling-rgba-images/88428/4 - """ - return Image.open(path).convert('RGB')
- - -
[docs]def mk_fun_label2onehot(dim): - """ - function generator - index to onehot - """ - def fun_label2onehot(label): - """ - :param label: - """ - m_eye = torch.eye(dim) - return m_eye[label] - return fun_label2onehot
- - -
[docs]def plot_ds(dset, f_name, batchsize=32): - """ - :param dset: - :param f_name: - :param batchsize: batch_size - """ - loader_tr = data_utils.DataLoader(dset, batch_size=batchsize, shuffle=False) - for _, (img, _, *_) in enumerate(loader_tr): - nrow = min(img.size(0), 8) - save_image(img.cpu(), f_name, nrow=nrow) - break # only one batch
- - -
[docs]def plot_ds_list(ds_list, f_name, batchsize=8, shuffle=False): - """ - plot list of datasets, each datasets in one row - :param ds_list: - :param fname: - :param batchsize: - :param shuffle: - """ - list_imgs = [] - for dset in ds_list: - loader = data_utils.DataLoader(dset, batch_size=batchsize, shuffle=shuffle) - for _, (img, _, *_) in enumerate(loader): - list_imgs.append(img) - break - comparison = torch.cat(list_imgs) - save_image(comparison.cpu(), f_name, nrow=batchsize)
- - -
[docs]class DsetInMemDecorator(Dataset): - """ - fetch all items of a dataset into memory - """ - def __init__(self, dset, name=None): - """ - :param dset: x, y, *d - :param name: name of dataset - """ - self.dset = dset - self.item_list = [] - if name is not None: - print("loading dset ", name) - t_0 = datetime.datetime.now() - for i in range(len(self.dset)): - self.item_list.append(self.dset[i]) - t_1 = datetime.datetime.now() - print("loading dataset to memory taken: ", t_1-t_0) - - def __getitem__(self, idx): - """ - :param idx: - """ - return self.item_list[idx] - - def __len__(self): - return self.dset.__len__()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/dsets/utils_wrapdset_patches.html b/docs/build/html/_modules/domainlab/dsets/utils_wrapdset_patches.html deleted file mode 100644 index 0c2819e54..000000000 --- a/docs/build/html/_modules/domainlab/dsets/utils_wrapdset_patches.html +++ /dev/null @@ -1,443 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets.utils_wrapdset_patches — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.dsets.utils_wrapdset_patches

-"""
-upon a task, if jigen is chosen as the algorithm, then task's dataset has to be augmented to
-include tile permutation
-"""
-import os
-import numpy as np
-import torch
-import torchvision
-from torchvision import transforms
-from torch.utils import data as torchdata
-
-
-
[docs]class WrapDsetPatches(torchdata.Dataset): - """ - given dataset of images, return permuations of tiles of images re-weaved - """ - def __init__(self, dataset, - num_perms2classify, - prob_no_perm, - grid_len, - ppath=None, - flag_do_not_weave_tiles=False): - """ - :param prob_no_perm: probability of no permutation - """ - if ppath is None and grid_len != 3: - raise RuntimeError("please provide npy file of numpy array with each row \ - being a permutation of the number of tiles, currently \ - we only support grid length 3") - self.dataset = dataset - self._to_tensor = transforms.Compose([transforms.ToTensor()]) - self.arr1perm_per_row = self.__retrieve_permutations( - num_perms2classify, ppath) - # for 3*3 tiles, there are 9*8*7*6*5*...*1 >> 100, - # we load from disk instead only 100 permutations - # each row of the loaded array is a permutation of the 3*3 tile - # of the original image - self.grid_len = grid_len - # break the image into 3*3 tiles - self.prob_no_perm = prob_no_perm - if flag_do_not_weave_tiles: - self.fun_weave_imgs = lambda x: x - else: - def make_grid(img): - """ - sew tiles together to be an image - """ - return torchvision.utils.make_grid( - img, nrow=self.grid_len, padding=0) - self.fun_weave_imgs = make_grid - -
[docs] def get_tile(self, img, ind_tile): - """ - assume a square image? - """ - img_height = img.shape[-1] - # @FIXME: use a better way to decide the image size - num_tiles = float(img_height) / self.grid_len - num_tiles = float(int(num_tiles)) + 1 - # @FIXME: extra line to ensure num_tiles=75 instead of sometimes 74 - # so torch.stack can fail in original data, - # num_tiles = float(img.size[0]) / self.grid_len = 225/3 = 75.0 - # is an integer, but this can not be true for other cases - ind_vertical = int(ind_tile / self.grid_len) - ind_horizontal = ind_tile % self.grid_len - functor_tr = transforms.ToPILImage() - img_pil = functor_tr(img) - # PIL.crop((left, top, right, bottom)) - # get rectangular region from box of [left, upper, right, lower] - tile = img_pil.crop([ind_horizontal * num_tiles, - ind_vertical * num_tiles, - (ind_horizontal + 1) * num_tiles, - (ind_vertical + 1) * num_tiles]) - tile = self._to_tensor(tile) - return tile
- - def __getitem__(self, index): - img, label, *_ = self.dataset.__getitem__(index) - num_grids = self.grid_len ** 2 - # divide image into grid_len^2 tiles - list_tiles = [None] * num_grids - # list of length num_grids of image tiles - for ind_tile in range(num_grids): - list_tiles[ind_tile] = self.get_tile(img, ind_tile) # populate tile list - ind_which_perm = np.random.randint( - self.arr1perm_per_row.shape[0] + 1) - # +1 in line above is for when image is not permutated, which - # also need to be classified corrected by the permutation classifier - # let len(self.arr1perm_per_row)=31 - # so ind_which_perm is a random number in [0, 31] in total 31+1 classes - # ind_which_perm is basically the row index to choose - # from self.arr1perm_per_row which is a matrix of 31*9 - # where 9=3*3 is the number of tiles the image is broken into - if self.prob_no_perm: # probability of no permutation of tiles - if self.prob_no_perm > np.random.rand(): - ind_which_perm = 0 - # ind_which_perm = 0 means no permutation, the classifier need to - # judge if the image has not been permutated as well - list_reordered_tiles = None - if ind_which_perm == 0: - list_reordered_tiles = list_tiles # no permutation - else: # default - perm_chosen = self.arr1perm_per_row[ind_which_perm - 1] - list_reordered_tiles = [list_tiles[perm_chosen[ind_tile]] - for ind_tile in range(num_grids)] - stacked_tiles = torch.stack(list_reordered_tiles, 0) - # the 0th dim is the batch dimension - # ind_which_perm = 0 means no permutation, the classifier need to - # judge if the image has not been permutated as well - return self.fun_weave_imgs(stacked_tiles), label, int(ind_which_perm) - # ind_which_perm is the ground truth for the permutation index - - def __len__(self): - return self.dataset.__len__() - - def __retrieve_permutations(self, num_perms_as_classes, ppath=None): - """ - for 9 tiles which partition the image, we have num_perms_as_classes - number of different permutations of the tiles, the classifier will - classify the re-tile-ordered image permutation it come from. - """ - # @FIXME: this assumes always a relative path - mdir = os.path.dirname(os.path.realpath(__file__)) - if ppath is None: - ppath = f'data/patches_permutation4jigsaw/permutations_{num_perms_as_classes}.npy' - mpath = os.path.join(mdir, "..", "..", ppath) - arr_permutation_rows = np.load(mpath) - # from range [1,9] to [0,8] since python array start with 0 - if arr_permutation_rows.min() == 1: - arr_permutation_rows = arr_permutation_rows - 1 - return arr_permutation_rows
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/exp_protocol/run_experiment.html b/docs/build/html/_modules/domainlab/exp_protocol/run_experiment.html deleted file mode 100644 index 9d6a50256..000000000 --- a/docs/build/html/_modules/domainlab/exp_protocol/run_experiment.html +++ /dev/null @@ -1,443 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.exp_protocol.run_experiment — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.exp_protocol.run_experiment

-"""
-Runs one task for a single hyperparameter sample for each leave-out-domain
-and each random seed.
-"""
-import gc
-import ast
-import warnings
-
-import pandas as pd
-import torch
-
-from domainlab.arg_parser import mk_parser_main
-from domainlab.compos.exp.exp_cuda_seed import set_seed
-from domainlab.compos.exp.exp_main import Exp
-from domainlab.compos.exp.exp_utils import ExpProtocolAggWriter
-
-
-
[docs]def load_parameters(file: str, index: int) -> tuple: - """ - Loads a single parameter sample - @param file: csv file - @param index: index of hyper-parameter - """ - param_df = pd.read_csv(file, index_col=0) - row = param_df.loc[index] - params = ast.literal_eval(row.params) - return row.task, params
- - -
[docs]def apply_dict_to_args(args, data: dict, extend=False, flag_warn=False): - """ - Tries to apply the data to the args dict of DomainLab. - Unknown keys are silently ignored as long as - extend is not set. - # FIXME: do we have a test to ensure args dict from - # domainlab really got what is passed from "data" dict? - """ - arg_dict = args.__dict__ - for key, value in data.items(): - if (key in arg_dict) or extend: - if isinstance(value, list): - cur_val = arg_dict.get(key, None) - if not isinstance(cur_val, list): - if cur_val is not None: - # @FIXME: should we warn or raise Error? - warnings.warn(f"input dictionary value is list, \ - however, in DomainLab args, we have {cur_val}, \ - going to overrite to list") - arg_dict[key] = [] - arg_dict[key].extend(value) - else: - arg_dict[key] = value - else: - if flag_warn: - warnings.warn(f"{key} does not exist in DomainLab, ignoring!")
- - -
[docs]def run_experiment( - config: dict, - param_file: str, - param_index: int, - out_file: str, - start_seed=None, - misc=None, -): - """ - Runs the experiment several times: - - for test_domain in test_domains: - for seed from startseed to endseed: - evaluate the algorithm with test_domain, initialization with seed - - :param config: dictionary from the benchmark yaml - :param param_file: path to the csv with the parameter samples - :param param_index: parameter index that should be covered by this task, - currently this correspond to the line number in the csv file, or row number - in the resulting pandas dataframe - :param out_file: path to the output csv - :param start_seed: random seed to start for stochastic variations of pytorch - :param misc: optional dictionary of additional parameters, if any. - - # FIXME: we might want to run the experiment using commandline arguments - """ - if misc is None: - misc = {} - task, hyperparameters = load_parameters(param_file, param_index) - # print("\n*******************************************************************") - # print(f"{task}, param_index={param_index}, params={hyperparameters}") - # print("*******************************************************************\n") - misc['result_file'] = out_file - misc['params'] = hyperparameters - misc['benchmark_task_name'] = task - misc['param_index'] = param_index - misc['keep_model'] = False - misc['no_dump'] = True - - parser = mk_parser_main() - args = parser.parse_args(args=[]) - apply_dict_to_args(args, config) - apply_dict_to_args(args, config[task]) - apply_dict_to_args(args, hyperparameters) - apply_dict_to_args(args, misc, extend=True) - - if torch.cuda.is_available(): - torch.cuda.init() - print("before experiment loop: ") - print(torch.cuda.memory_summary()) - if start_seed is None: - start_seed = config['startseed'] - end_seed = config['endseed'] - else: - end_seed = start_seed + (config['endseed'] - config['startseed']) - - for te_d in config['test_domains']: - args.te_d = te_d - for seed in range(start_seed, end_seed + 1): - set_seed(seed) - args.seed = seed - if torch.cuda.is_available(): - print(torch.cuda.memory_summary()) - exp = Exp(args=args, visitor=ExpProtocolAggWriter) - if not misc.get('testing', False): - exp.execute() - del exp - torch.cuda.empty_cache() - gc.collect() - try: - if torch.cuda.is_available(): - print(torch.cuda.memory_summary()) - except KeyError as ex: - print(ex)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/a_model.html b/docs/build/html/_modules/domainlab/models/a_model.html deleted file mode 100644 index cde45aa60..000000000 --- a/docs/build/html/_modules/domainlab/models/a_model.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.a_model — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.a_model

-"""
-operations that all kinds of models should have
-"""
-
-import abc
-
-from torch import nn
-
-
-
[docs]class AModel(nn.Module, metaclass=abc.ABCMeta): - """ - operations that all models (classification, segmentation, seq2seq) - """ -
[docs] def cal_loss(self, tensor_x, tensor_y, tensor_d, others=None): - """ - calculate the loss - """ - return self.cal_task_loss(tensor_x, tensor_y) + \ - self.cal_reg_loss(tensor_x, tensor_y, tensor_d, others)
- -
[docs] @abc.abstractmethod - def cal_task_loss(self, tensor_x, tensor_y): - """ - Calculate the task loss - - :param tensor_x: input - :param tensor_y: label - :return: task loss - """
- -
[docs] @abc.abstractmethod - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - """ - task independent regularization loss for domain generalization - """
- -
[docs] def forward(self, tensor_x, tensor_y, tensor_d, others=None): - """forward. - - :param x: - :param y: - :param d: - """ - return self.cal_loss(tensor_x, tensor_y, tensor_d, others)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/a_model_classif.html b/docs/build/html/_modules/domainlab/models/a_model_classif.html deleted file mode 100644 index 921178f5a..000000000 --- a/docs/build/html/_modules/domainlab/models/a_model_classif.html +++ /dev/null @@ -1,475 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.a_model_classif — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.a_model_classif

-"""
-operations that all claasification model should have
-"""
-
-import abc
-import numpy as np
-import torch
-from torch import nn as nn
-from torch.nn import functional as F
-
-from domainlab.models.a_model import AModel
-from domainlab.utils.utils_class import store_args
-from domainlab.utils.utils_classif import get_label_na, logit2preds_vpic
-from domainlab.utils.perf import PerfClassif
-from domainlab.utils.perf_metrics import PerfMetricClassif
-from rich import print as rprint
-import pandas as pd
-
-
-
[docs]class AModelClassif(AModel, metaclass=abc.ABCMeta): - """ - operations that all classification model should have - """ - match_feat_fun_na = "cal_logit_y" - -
[docs] def create_perf_obj(self, task): - """ - for classification, dimension of target can be quieried from task - """ - self.perf_metric = PerfMetricClassif(task.dim_y) - return self.perf_metric
- -
[docs] def cal_perf_metric(self, loader_tr, device, loader_te=None): - """ - classification performance matric - """ - metric_te = None - metric_tr_pool = self.perf_metric.cal_metrics(self, loader_tr, device) - confmat = metric_tr_pool.pop("confmat") - print("pooled train domains performance:") - rprint(metric_tr_pool) - print("confusion matrix:") - print(pd.DataFrame(confmat)) - metric_tr_pool["confmat"] = confmat - # test set has no domain label, so can be more custom - if loader_te is not None: - metric_te = self.perf_metric.cal_metrics(self, loader_te, device) - confmat = metric_te.pop("confmat") - print("out of domain test performance:") - rprint(metric_te) - print("confusion matrix:") - print(pd.DataFrame(confmat)) - metric_te["confmat"] = confmat - return metric_te
- -
[docs] def evaluate(self, loader_te, device): - """ - for classification task, use the current model to cal acc - """ - acc = PerfClassif.cal_acc(self, loader_te, device) - print("before training, model accuracy:", acc)
- -
[docs] @abc.abstractmethod - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """
- - @store_args - def __init__(self, list_str_y, list_d_tr=None): - """ - :param list_str_y: list of fixed order, each element is a class label - """ - super().__init__() - self.list_str_y = list_str_y - self.list_d_tr = list_d_tr - self.perf_metric = None - self.loss4gen_adv = nn.KLDivLoss(size_average=False) - -
[docs] def infer_y_vpicn(self, tensor): - """ - :param tensor: input - :return: vpicn - v: vector of one-hot class label, - p: vector of probability, - i: class label index, - c: confidence: maximum probability, - n: list of name of class - """ - with torch.no_grad(): - logit_y = self.cal_logit_y(tensor) - vec_one_hot, prob, ind, confidence = logit2preds_vpic(logit_y) - na_class = get_label_na(ind, self.list_str_y) - return vec_one_hot, prob, ind, confidence, na_class
- - @property - def dim_y(self): - """ - the class embedding dimension - """ - return len(self.list_str_y) - -
[docs] def cal_task_loss(self, tensor_x, tensor_y): - """ - Calculate the task loss. Used within the `cal_loss` methods of models - that are subclasses of `AModelClassif`. Cross entropy loss for - classification is used here by default but could be modified by - subclasses - as necessary. - - :param tensor_x: input - :param tensor_y: label - :return: task loss - """ - logit_y = self.cal_logit_y(tensor_x) - if (tensor_y.shape[-1] == 1) | (len(tensor_y.shape) == 1): - y_target = tensor_y - else: - _, y_target = tensor_y.max(dim=1) - lc_y = F.cross_entropy(logit_y, y_target, reduction="none") - return lc_y
- -
[docs] def pred2file(self, loader_te, device, - filename='path_prediction.txt', flag_pred_scalar=False): - """ - pred2file dump predicted label to file as sanity check - """ - self.eval() - model_local = self.to(device) - for _, (x_s, y_s, *_, path) in enumerate(loader_te): - x_s, y_s = x_s.to(device), y_s.to(device) - _, prob, *_ = model_local.infer_y_vpicn(x_s) - # print(path) - list_pred_list = prob.tolist() - list_label_list = y_s.tolist() - if flag_pred_scalar: - list_pred_list = [np.asarray(pred).argmax() for pred in list_pred_list] - list_label_list = [np.asarray(label).argmax() for label in list_label_list] - # label belongs to data - list_pair_path_pred = list(zip(path, list_label_list, list_pred_list)) - with open(filename, 'a', encoding="utf8") as handle_file: - for pair in list_pair_path_pred: - # 1:-1 removes brackets of tuple - print(str(pair)[1:-1], file=handle_file) - print("prediction saved in file ", filename)
- -
[docs] def cal_loss_gen_adv(self, x_natural, x_adv, vec_y): - """ - calculate loss function for generation of adversarial images - """ - x_adv.requires_grad_() - with torch.enable_grad(): - logits_adv = self.cal_logit_y(x_adv) - logits_natural = self.cal_logit_y(x_natural) - prob_adv = F.log_softmax(logits_adv, dim=1) - prob_natural = F.softmax(logits_natural, dim=1) - loss_adv_gen_task = self.cal_task_loss(x_adv, vec_y) - loss_adv_gen = self.loss4gen_adv(prob_adv, prob_natural) - return loss_adv_gen + loss_adv_gen_task.sum()
- -
[docs] def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - return 0
- -
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/args_jigen.html b/docs/build/html/_modules/domainlab/models/args_jigen.html deleted file mode 100644 index 35dc6c2be..000000000 --- a/docs/build/html/_modules/domainlab/models/args_jigen.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.args_jigen — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.args_jigen

-"""
-hyper-parameters for JiGen
-"""
-
[docs]def add_args2parser_jigen(parser): - """ - hyper-parameters for JiGen - """ - parser.add_argument('--nperm', type=int, default=31, - help='number of permutations') - parser.add_argument('--pperm', type=float, default=0.7, - help='probability of permutating the tiles \ - of an image') - parser.add_argument('--jigen_ppath', type=str, default=None, - help='npy file path to load numpy array with each row being \ - permutation index, if not None, nperm and grid_len has to agree \ - with the number of row and columns of the input array') - parser.add_argument('--grid_len', type=int, default=3, - help='length of image in tile unit') - return parser
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/args_vae.html b/docs/build/html/_modules/domainlab/models/args_vae.html deleted file mode 100644 index 3d6d7d228..000000000 --- a/docs/build/html/_modules/domainlab/models/args_vae.html +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.args_vae — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.args_vae

-
[docs]def add_args2parser_vae(parser): - parser.add_argument('--zd_dim', type=int, default=64, - help='size of latent space for domain') - parser.add_argument('--zx_dim', type=int, default=0, - help='size of latent space for unobserved') - parser.add_argument('--zy_dim', type=int, default=64, - help='size of latent space for class') - # HDUVA - parser.add_argument('--topic_dim', type=int, default=3, - help='dim latent space for topic') - - parser.add_argument('--topic_h_dim', type=int, default=8, - help='dim latent space for topic') - - parser.add_argument('--img_h_dim', type=int, default=8, - help='dim latent space for topic') - - parser.add_argument('--nname_topic_distrib_img2topic', - type=str, default=None, - help='network from image to topic distribution') - parser.add_argument('--npath_topic_distrib_img2topic', - type=str, default=None, - help='network from image to topic distribution') - - parser.add_argument('--nname_encoder_sandwich_layer_img2h4zd', - type=str, default=None, - help='network from image to topic distribution') - parser.add_argument('--npath_encoder_sandwich_layer_img2h4zd', - type=str, default=None, - help='network from image to topic distribution') - - # ERM, ELBO - parser.add_argument('--gamma_y', type=float, default=None, - help='multiplier for y classifier') - parser.add_argument('--gamma_d', type=float, default=None, - help='multiplier for d classifier from zd') - - - - # Beta VAE part - parser.add_argument('--beta_t', type=float, default=1., - help='multiplier for KL topic') - parser.add_argument('--beta_d', type=float, default=1., - help='multiplier for KL d') - parser.add_argument('--beta_x', type=float, default=1., - help='multiplier for KL x') - parser.add_argument('--beta_y', type=float, default=1., - help='multiplier for KL y') - # - - parser.add_argument('-w', '--warmup', type=int, default=100, - help='number of epochs for hyper-parameter warm-up. \ - Set to 0 to turn warmup off.') - return parser
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_custom.html b/docs/build/html/_modules/domainlab/models/model_custom.html deleted file mode 100644 index f7ba4bb78..000000000 --- a/docs/build/html/_modules/domainlab/models/model_custom.html +++ /dev/null @@ -1,361 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_custom — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_custom

-import abc
-
-import torch
-
-from domainlab.models.a_model_classif import AModelClassif
-from domainlab.utils.utils_classif import get_label_na, logit2preds_vpic
-
-
-
[docs]class AModelCustom(AModelClassif): - """AModelCustom.""" - - def __init__(self, list_str_y, list_str_d=None): - """__init__. - :param net: - :param list_str_y: - :param list_str_d: - """ - super().__init__(list_str_y, list_str_d) - - @property - @abc.abstractmethod - def dict_net_module_na2arg_na(self): - """dict_net_module_na2arg_na. - A dictionary with the key being the pytorch module name and value - being the commandline argument name - """ - raise NotImplementedError - -
[docs] def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - raise NotImplementedError
- -
[docs] def infer_y_vpicn(self, tensor): - """ - :param tensor: input - :return: - - v - vector of one-hot class label - - p - vector of probability - - i - class label index - - c - confidence: maximum probability - - n - list of name of class - """ - with torch.no_grad(): - logit_y = self.cal_logit_y(tensor) - vec_one_hot, prob, ind, confidence = logit2preds_vpic(logit_y) - na_class = get_label_na(ind, self.list_str_y) - return vec_one_hot, prob, ind, confidence, na_class
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_dann.html b/docs/build/html/_modules/domainlab/models/model_dann.html deleted file mode 100644 index d5223e37a..000000000 --- a/docs/build/html/_modules/domainlab/models/model_dann.html +++ /dev/null @@ -1,367 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_dann — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_dann

-from torch.nn import functional as F
-
-from domainlab.compos.nn_zoo.net_adversarial import AutoGradFunReverseMultiply
-from domainlab.models.a_model_classif import AModelClassif
-
-
[docs]def mk_dann(parent_class=AModelClassif): - """Instantiate a Deep Adversarial Net (DAN) model - - Args: - parent_class (AModel, optional): Class object determining the task - type. Defaults to AModelClassif. - - Returns: - ModelDAN: model inheriting from parent class - """ - class ModelDAN(parent_class): - """ - anonymous - """ - def __init__(self, list_str_y, list_str_d, - alpha, net_encoder, net_classifier, net_discriminator): - super().__init__(list_str_y, list_str_d) - self.alpha = alpha - self.net_encoder = net_encoder - self.net_classifier = net_classifier - self.net_discriminator = net_discriminator - - def hyper_update(self, epoch, fun_scheduler): - """hyper_update. - :param epoch: - :param fun_scheduler: - """ - dict_rst = fun_scheduler(epoch) - self.alpha = dict_rst["alpha"] - - def hyper_init(self, functor_scheduler): - """hyper_init. - :param functor_scheduler: - """ - return functor_scheduler(alpha=self.alpha) - - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - return self.net_classifier(self.net_encoder(tensor_x)) - - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - feat = self.net_encoder(tensor_x) - logit_d = self.net_discriminator( - AutoGradFunReverseMultiply.apply(feat, self.alpha)) - _, d_target = tensor_d.max(dim=1) - lc_d = F.cross_entropy(logit_d, d_target, reduction="none") - return self.alpha*lc_d - return ModelDAN
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_deep_all.html b/docs/build/html/_modules/domainlab/models/model_deep_all.html deleted file mode 100644 index 0c876913b..000000000 --- a/docs/build/html/_modules/domainlab/models/model_deep_all.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_deep_all — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_deep_all

-from domainlab.models.a_model_classif import AModelClassif
-from domainlab.utils.override_interface import override_interface
-
-
-
[docs]def mk_deepall(parent_class=AModelClassif): - """Instantiate a Deepall model - - Args: - parent_class (AModel, optional): - Class object determining the task type. Defaults to AModelClassif. - - Returns: - ModelDeepAlll: model inheriting from parent class - """ - class ModelDeepAll(parent_class): - """ - anonymous - """ - def __init__(self, net, list_str_y, list_str_d=None): - super().__init__(list_str_y, list_str_d) - self.add_module("net", net) - - @override_interface(AModelClassif) - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - logit_y = self.net(tensor_x) - return logit_y - - def forward(self, tensor_x, tensor_y, tensor_d, others=None): - return self.cal_loss(tensor_x, tensor_y, tensor_d) - - def cal_loss(self, tensor_x, tensor_y, tensor_d, others=None): - lc_y = self.cal_task_loss(tensor_x, tensor_y) - return lc_y - - return ModelDeepAll
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_diva.html b/docs/build/html/_modules/domainlab/models/model_diva.html deleted file mode 100644 index 42eebbd18..000000000 --- a/docs/build/html/_modules/domainlab/models/model_diva.html +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_diva — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_diva

-"""
-DIVA
-"""
-import torch
-from torch.nn import functional as F
-
-from domainlab.models.model_vae_xyd_classif import VAEXYDClassif
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]def mk_diva(parent_class=VAEXYDClassif): - """ - DIVA with arbitrary task loss - """ - class ModelDIVA(parent_class): - """ - DIVA - """ - @store_args - def __init__(self, chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_d_tr, - gamma_d, gamma_y, - beta_d, beta_x, beta_y): - """ - gamma: classification loss coefficient - """ - super().__init__(chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_d_tr) - self.dim_d_tr = len(self.list_d_tr) - if self.zd_dim > 0: - self.add_module( - "net_p_zd", - self.chain_node_builder.construct_cond_prior( - self.dim_d_tr, self.zd_dim)) - self.add_module( - "net_classif_d", - self.chain_node_builder.construct_classifier( - self.zd_dim, self.dim_d_tr)) - - def hyper_update(self, epoch, fun_scheduler): - """hyper_update. - - :param epoch: - :param fun_scheduler: - """ - dict_rst = fun_scheduler(epoch) - self.beta_d = dict_rst["beta_d"] - self.beta_y = dict_rst["beta_y"] - self.beta_x = dict_rst["beta_x"] - - def hyper_init(self, functor_scheduler): - """hyper_init. - :param functor_scheduler: - """ - return functor_scheduler( - beta_d=self.beta_d, beta_y=self.beta_y, beta_x=self.beta_x) - - def get_list_str_y(self): - """get_list_str_y.""" - return self._list_str_y - - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - q_zd, zd_q, q_zx, zx_q, q_zy, zy_q = self.encoder(tensor_x) - logit_d = self.net_classif_d(zd_q) - - batch_size = zd_q.shape[0] - device = zd_q.device - - p_zx = self.init_p_zx4batch(batch_size, device) - p_zy = self.net_p_zy(tensor_y) - p_zd = self.net_p_zd(tensor_d) - - z_concat = self.decoder.concat_ydx(zy_q, zd_q, zx_q) - loss_recon_x, _, _ = self.decoder(z_concat, tensor_x) - - zd_p_minus_zd_q = torch.sum( - p_zd.log_prob(zd_q) - q_zd.log_prob(zd_q), 1) - zx_p_minus_zx_q = torch.sum( - p_zx.log_prob(zx_q) - q_zx.log_prob(zx_q), 1) - zy_p_minus_zy_q = torch.sum( - p_zy.log_prob(zy_q) - q_zy.log_prob(zy_q), 1) - - _, d_target = tensor_d.max(dim=1) - lc_d = F.cross_entropy(logit_d, d_target, reduction="none") - - return loss_recon_x \ - - self.beta_d * zd_p_minus_zd_q \ - - self.beta_x * zx_p_minus_zx_q \ - - self.beta_y * zy_p_minus_zy_q \ - + self.gamma_d * lc_d - return ModelDIVA
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_hduva.html b/docs/build/html/_modules/domainlab/models/model_hduva.html deleted file mode 100644 index fd274e0a8..000000000 --- a/docs/build/html/_modules/domainlab/models/model_hduva.html +++ /dev/null @@ -1,448 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_hduva — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_hduva

-"""
-Hierarchical Domain Unsupervised Variational Auto-Encoding
-"""
-import torch
-from torch.distributions import Dirichlet
-
-from domainlab.models.model_vae_xyd_classif import VAEXYDClassif
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]def mk_hduva(parent_class=VAEXYDClassif): - """ - Hierarchical Domain Unsupervised VAE with arbitrary task loss - """ - class ModelHDUVA(parent_class): - """ - Hierarchical Domain Unsupervised Variational Auto-Encoding - """ - def hyper_update(self, epoch, fun_scheduler): - """hyper_update. - - :param epoch: - :param fun_scheduler: - """ - dict_rst = fun_scheduler(epoch) - self.beta_d = dict_rst["beta_d"] - self.beta_y = dict_rst["beta_y"] - self.beta_x = dict_rst["beta_x"] - self.beta_t = dict_rst["beta_t"] - - def hyper_init(self, functor_scheduler): - """hyper_init. - :param functor_scheduler: - """ - return functor_scheduler( - beta_d=self.beta_d, beta_y=self.beta_y, beta_x=self.beta_x, - beta_t=self.beta_t) - - @store_args - def __init__(self, chain_node_builder, - zy_dim, zd_dim, - list_str_y, list_d_tr, - gamma_d, gamma_y, - beta_d, beta_x, beta_y, - beta_t, - device, - zx_dim=0, - topic_dim=3): - """ - """ - super().__init__(chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_d_tr) - - # topic to zd follows Gaussian distribution - self.add_module("net_p_zd", - self.chain_node_builder.construct_cond_prior( - self.topic_dim, self.zd_dim)) - - def _init_components(self): - """ - q(z|x) - p(zy) - q_{classif}(zy) - """ - self.add_module("encoder", self.chain_node_builder.build_encoder( - self.device, self.topic_dim)) - self.add_module("decoder", self.chain_node_builder.build_decoder( - self.topic_dim)) - self.add_module("net_p_zy", - self.chain_node_builder.construct_cond_prior( - self.dim_y, self.zy_dim)) - self.add_module("net_classif_y", - self.chain_node_builder.construct_classifier( - self.zy_dim, self.dim_y)) - - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - _, _, \ - _, _, \ - _, _, \ - _, zy_q = self.encoder(tensor_x) - logit_y = self.net_classif_y(zy_q) - return logit_y - - def init_p_topic_batch(self, batch_size, device): - """ - flat prior - """ - prior = Dirichlet(torch.ones(batch_size, self.topic_dim).to(device)) - return prior - - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - q_topic, topic_q, \ - qzd, zd_q, \ - qzx, zx_q, \ - qzy, zy_q = self.encoder(tensor_x) - - batch_size = zd_q.shape[0] - device = zd_q.device - - p_topic = self.init_p_topic_batch(batch_size, device) - - # zx KL divergence - zx_p_minus_q = 0 - if self.zx_dim > 0: - p_zx = self.init_p_zx4batch(batch_size, device) - zx_p_minus_q = torch.sum(p_zx.log_prob(zx_q) - qzx.log_prob(zx_q), 1) - - # @FIXME: does monte-carlo KL makes the performance unstable? - # from torch.distributions import kl_divergence - - # zy KL divergence - p_zy = self.net_p_zy(tensor_y) - zy_p_minus_zy_q = torch.sum(p_zy.log_prob(zy_q) - qzy.log_prob(zy_q), 1) - - # zd KL diverence - p_zd = self.net_p_zd(topic_q) - zd_p_minus_q = torch.sum(p_zd.log_prob(zd_q) - qzd.log_prob(zd_q), 1) - - # topic KL divergence - # @FIXME: why topic is still there? - topic_p_minus_q = p_topic.log_prob(topic_q) - q_topic.log_prob(topic_q) - - # reconstruction - z_concat = self.decoder.concat_ytdx(zy_q, topic_q, zd_q, zx_q) - loss_recon_x, _, _ = self.decoder(z_concat, tensor_x) - batch_loss = loss_recon_x \ - - self.beta_x * zx_p_minus_q \ - - self.beta_y * zy_p_minus_zy_q \ - - self.beta_d * zd_p_minus_q \ - - self.beta_t * topic_p_minus_q - return batch_loss - return ModelHDUVA
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_jigen.html b/docs/build/html/_modules/domainlab/models/model_jigen.html deleted file mode 100644 index 029f4061d..000000000 --- a/docs/build/html/_modules/domainlab/models/model_jigen.html +++ /dev/null @@ -1,371 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_jigen — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_jigen

-"""
-Jigen Model Similar to DANN model
-"""
-from torch.nn import functional as F
-
-from domainlab.models.a_model_classif import AModelClassif
-from domainlab.models.model_dann import mk_dann
-
-
-
[docs]def mk_jigen(parent_class=AModelClassif): - """Instantiate a JiGen model - - Args: - parent_class (AModel, optional): Class object determining the task - type. Defaults to AModelClassif. - - Returns: - ModelJiGen: model inheriting from parent class - """ - class_dann = mk_dann(parent_class) - - class ModelJiGen(class_dann): - """ - Jigen Model Similar to DANN model - """ - def __init__(self, list_str_y, list_str_d, - net_encoder, - net_classifier_class, - net_classifier_permutation, - coeff_reg): - super().__init__(list_str_y, list_str_d, - alpha=coeff_reg, - net_encoder=net_encoder, - net_classifier=net_classifier_class, - net_discriminator=net_classifier_permutation) - self.net_encoder = net_encoder - self.net_classifier_class = net_classifier_class - self.net_classifier_permutation = net_classifier_permutation - - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - """ - JiGen don't need domain label but a pre-defined permutation index - to calculate regularization loss - - We don't know if tensor_x is an original/un-tile-shuffled image or - a permutated image, which is the task of cal_reg_loss to classify - which permutation has been used or no permutation has been used at - all (which also has to be classified) - """ - vec_perm_ind = tensor_d - # tensor_x can be either original image or tile-shuffled image - feat = self.net_encoder(tensor_x) - logits_which_permutation = self.net_classifier_permutation(feat) - # _, batch_target_scalar = vec_perm_ind.max(dim=1) - batch_target_scalar = vec_perm_ind - loss_perm = F.cross_entropy( - logits_which_permutation, batch_target_scalar, reduction="none") - return self.alpha*loss_perm - return ModelJiGen
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/model_vae_xyd_classif.html b/docs/build/html/_modules/domainlab/models/model_vae_xyd_classif.html deleted file mode 100644 index 6ba46b0aa..000000000 --- a/docs/build/html/_modules/domainlab/models/model_vae_xyd_classif.html +++ /dev/null @@ -1,377 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.model_vae_xyd_classif — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.model_vae_xyd_classif

-"""
-Base Class for XYD VAE
-"""
-import torch
-import torch.distributions as dist
-
-from domainlab.models.a_model_classif import AModelClassif
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]class VAEXYDClassif(AModelClassif): - """ - Base Class for XYD VAE - """ - @store_args - def __init__(self, chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_str_d): - """ - :param chain_node_builder: constructed object - """ - super().__init__(list_str_y, list_str_d) - self.chain_node_builder.init_business( - self.zd_dim, self.zx_dim, self.zy_dim) - self.i_c = self.chain_node_builder.i_c - self.i_h = self.chain_node_builder.i_h - self.i_w = self.chain_node_builder.i_w - self._init_components() - -
[docs] def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - zy_q_loc = self.encoder.infer_zy_loc(tensor_x) - logit_y = self.net_classif_y(zy_q_loc) - return logit_y
- - def _init_components(self): - """ - q(z|x) - p(zy) - q_{classif}(zy) - """ - self.add_module("encoder", self.chain_node_builder.build_encoder()) - self.add_module("decoder", self.chain_node_builder.build_decoder()) - self.add_module("net_p_zy", - self.chain_node_builder.construct_cond_prior( - self.dim_y, self.zy_dim)) - self.add_module("net_classif_y", - self.chain_node_builder.construct_classifier( - self.zy_dim, self.dim_y)) - -
[docs] def init_p_zx4batch(self, batch_size, device): - """ - 1. Generate pytorch distribution object. - 2. To be called by trainer - - :param batch_size: - :param device: - """ - # p(zx): isotropic gaussian - zx_p_loc = torch.zeros(batch_size, self.zx_dim).to(device) - zx_p_scale = torch.ones(batch_size, self.zx_dim).to(device) - p_zx = dist.Normal(zx_p_loc, zx_p_scale) - return p_zx
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/models/wrapper_matchdg.html b/docs/build/html/_modules/domainlab/models/wrapper_matchdg.html deleted file mode 100644 index 265d0491e..000000000 --- a/docs/build/html/_modules/domainlab/models/wrapper_matchdg.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models.wrapper_matchdg — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.models.wrapper_matchdg

-"""
-Wrapper for MatchDG to conform of model class in DomainLab
-"""
-from domainlab.models.a_model_classif import AModelClassif
-
-
-
[docs]class ModelWrapMatchDGLogit(AModelClassif): - """ - Wrap an arbitrary model with interface:cal_logit_y - """ - def __init__(self, net, list_str_y, list_str_d=None): - super().__init__(list_str_y, list_str_d) - fun_name = AModelClassif.match_feat_fun_na - if not hasattr(net, fun_name): - raise RuntimeError( - "model to be wrapped must inherit base class ", - str(AModelClassif.__class__), - " with attribute:", fun_name) - self.net = net - -
[docs] def cal_logit_y(self, tensor_x): - return self.net.cal_logit_y(tensor_x)
- -
[docs] def cal_loss(self, tensor_x, tensor_y, tensor_d=None, others=None): - return self.net.cal_loss(tensor_x, tensor_y, tensor_d)
- -
[docs] def cal_reg_loss(self, tensor_x, tensor_y, tensor_d=None, others=None): - return self.net.cal_loss(tensor_x, tensor_y, tensor_d) # @FIXME: this is wrong
- -
[docs] def forward(self, tensor_x): - """ - calculate features to be matched - """ - logit_y = self.net.cal_logit_y(tensor_x) # @FIXME: match other features instead of logit - return logit_y
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/a_task_classif.html b/docs/build/html/_modules/domainlab/tasks/a_task_classif.html deleted file mode 100644 index 689873b1a..000000000 --- a/docs/build/html/_modules/domainlab/tasks/a_task_classif.html +++ /dev/null @@ -1,485 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.a_task_classif — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.a_task_classif

-"""
-Abstract class for TaskClassif
-"""
-import os
-import warnings
-from abc import abstractmethod, abstractproperty
-
-from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler
-from domainlab.tasks.utils_task import img_loader2dir
-from domainlab.tasks.task_utils import parse_domain_id
-
-
-
[docs]class NodeTaskDGClassif(AbstractChainNodeHandler): - """ - Domain Generalization Classification Task - """ - def __init__(self, succ=None): - super().__init__(succ) - self._loader_tr = None - self._loader_te = None - self._loader_val = None - self._list_domains = None - self._list_domain_tr = None - self.dict_dset = {} - self.dict_dset_te = {} - self.dict_dset_val = {} - self.dict_domain_class_count = {} - self.dim_d_tr = None # public - self._list_str_y = None - self._im_size = None - self._dict_domains2imgroot = {} - self._dict_domain_folder_name2class = {} # {"domain1": {"class1":car, "class2":dog}} - self._dict_domain_img_trans = {} - self._dict_domain2filepath_list_im = {} # {"photo": "xxx/yyy/file_of_path2imgs"} - self.dict_att = {} - self.img_trans_te = None - -
[docs] @abstractmethod - def init_business(self, args): - """ - construct loader with resampling - :param seed: random seed for resampling - :param bs: batch size - :param domain_na_tes: test domain names - """
- -
[docs] @abstractmethod - def get_list_domains(self): - """ - 1. get list of domain names - 2. better use method than property so new domains can be added - """ - raise NotImplementedError
- - @abstractproperty - def list_str_y(self): - raise NotImplementedError - - @abstractproperty - def isize(self): - """image channel, height, width""" - raise NotImplementedError - - ########################################################################### - @property - def dim_y(self): - """classification dimension""" - return len(self.list_str_y) - - @property - def list_domain_tr(self): - """ - property getter of list of domains for this task - """ - if self._list_domain_tr is None: - raise RuntimeError("task not intialized!") - return self._list_domain_tr - - @property - def loader_tr(self): - """loader of mixed train domains""" - return self._loader_tr - - @property - def loader_val(self): - """loader of validation dataset on the training domains""" - return self._loader_val - - @property - def loader_te(self): - """loader of mixed test domains""" - return self._loader_te - - @property - def task_name(self): - """ - The basic name of the task, without configurations - """ - # @FIXME: hardcoded position - return type(self).__name__[8:].lower() - -
[docs] def get_na(self, na_tr, na_te): - """ - task name appended with configurations - :param na_tr: training domain names - :param na_te: test domain names - """ - _, list_te = self.get_list_domains_tr_te(na_tr, na_te) - str_te = "_".join(list_te) - # train domain names are too long - return "_".join([self.task_name, "te", str_te])
- -
[docs] def is_myjob(self, request): - """ - :param request: string - """ - return request == self.task_name
- -
[docs] def get_list_domains_tr_te(self, tr_id, te_id): - """ - For static DG task, get train and test domains list. - - :param tr_id: training domain ids; - int or str, or a list of int or str, or None; - if None, then assumed to be the complement of te_id. - :param te_id: test domain ids; - int or str, or a list of int or str; required. - :return: list of training domain names, list of test domain names. - """ - list_domains = self.get_list_domains() - - list_domain_te = parse_domain_id(te_id, list_domains) - assert set(list_domain_te).issubset(set(list_domains)) - - if tr_id is None: - list_domain_tr = [did for did in list_domains if - did not in list_domain_te] - else: - list_domain_tr = parse_domain_id(tr_id, list_domains) - if not set(list_domain_tr).issubset(set(list_domains)): - raise RuntimeError( - f"training domain {list_domain_tr} is not \ - subset of available domains {list_domains}") - - if set(list_domain_tr) & set(list_domain_te): - warnings.warn( - "The sets of training and test domains overlap -- \ - be aware of data leakage or training to the test!", - RuntimeWarning - ) - - self.dim_d_tr = len(list_domain_tr) - self._list_domain_tr = list_domain_tr - return list_domain_tr, list_domain_te
- -
[docs] def sample_sav(self, root, batches=5, subfolder_na="task_sample"): - """ - sample data from task and save to disk - """ - folder_na = os.path.join(root, self.task_name, subfolder_na) - - img_loader2dir(self.loader_te, - list_domain_na=self.get_list_domains(), - list_class_na=self.list_str_y, - folder=folder_na, - batches=batches, - test=True) - - img_loader2dir(self.loader_tr, - list_domain_na=self.get_list_domains(), - list_class_na=self.list_str_y, - folder=folder_na, - batches=batches)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/b_task.html b/docs/build/html/_modules/domainlab/tasks/b_task.html deleted file mode 100644 index ffc497b3d..000000000 --- a/docs/build/html/_modules/domainlab/tasks/b_task.html +++ /dev/null @@ -1,437 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.b_task — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.b_task

-"""
-Use dictionaries to create train and test domain split
-"""
-from collections import Counter
-
-import torch
-from torch.utils.data.dataset import ConcatDataset
-
-from domainlab.tasks.a_task_classif import NodeTaskDGClassif
-from domainlab.tasks.utils_task import (DsetDomainVecDecorator, mk_loader,
-                                        mk_onehot)
-
-
-
[docs]class NodeTaskDict(NodeTaskDGClassif): - """ - Use dictionaries to create train and test domain split - """ - @property - def list_str_y(self): - return self._list_str_y - - @list_str_y.setter - def list_str_y(self, list_str_y): - self._list_str_y = list_str_y - - @property - def isize(self): - return self._im_size - - @isize.setter - def isize(self, im_size): - self._im_size = im_size - -
[docs] def get_list_domains(self): - return self._list_domains
- -
[docs] def set_list_domains(self, list_domains): - """ - setter for self._list_domains - """ - self._list_domains = list_domains
- -
[docs] def get_dset_by_domain(self, args, na_domain, split=False): - """ - each domain correspond to one dataset - """ - raise NotImplementedError
- -
[docs] def decorate_dset(self, model, args): - """ - dispatch re-organization of data flow to model - """
- -
[docs] def init_business(self, args): - """ - create a dictionary of datasets - """ - # @FIXME - from domainlab.algos.zoo_algos import AlgoBuilderChainNodeGetter - # ImportError: cannot import name 'AlgoBuilderChainNodeGetter' - # from partially initialized module 'domainlab.algos.zoo_algos' - # (most likely due to a circular import) - # (~/domainlab_master/domainlab/algos/zoo_algos.py) - node = AlgoBuilderChainNodeGetter(args)() - list_domain_tr, list_domain_te = self.get_list_domains_tr_te(args.tr_d, args.te_d) - self.dict_dset = {} - self.dict_dset_val = {} - dim_d = len(list_domain_tr) - for (ind_domain_dummy, na_domain) in enumerate(list_domain_tr): - # FIXME: specify either split = True or False - dset_tr, dset_val = self.get_dset_by_domain(args, na_domain) - # @FIXME: currently, different task has different default values for - # split, for TaskFolder split default to False, for mnist, split - # default to True - vec_domain = mk_onehot(dim_d, ind_domain_dummy) - ddset_tr = DsetDomainVecDecorator(dset_tr, vec_domain, na_domain) - ddset_val = DsetDomainVecDecorator(dset_val, vec_domain, na_domain) - ddset_tr = node.dset_decoration_args_algo(args, ddset_tr) - ddset_val = node.dset_decoration_args_algo(args, ddset_val) - self.dict_dset.update({na_domain: ddset_tr}) - self.dict_dset_val.update({na_domain: ddset_val}) - ddset_mix = ConcatDataset(tuple(self.dict_dset.values())) - self._loader_tr = mk_loader(ddset_mix, args.bs) - - ddset_mix_val = ConcatDataset(tuple(self.dict_dset_val.values())) - self._loader_val = mk_loader(ddset_mix_val, args.bs) - - self.dict_dset_te = {} - # No need to have domain Label for test - for na_domain in list_domain_te: - dset_te, *_ = self.get_dset_by_domain(args, na_domain, split=False) - # @FIXME: since get_dset_by_domain always return two datasets, - # train and validation, this is not needed in test domain - self.dict_dset_te.update({na_domain: dset_te}) - dset_te = ConcatDataset(tuple(self.dict_dset_te.values())) - self._loader_te = mk_loader(dset_te, args.bs, drop_last=False) - self.count_domain_class()
- -
[docs] def count_domain_class(self): - """ - iterate all domains and count the class label distribution for each - return a double dictionary {"domain1": {"class1":3, "class2": 4,...}, ....} - """ - for key, dset in self.dict_dset.items(): - dict_class_count = self._count_class_one_hot(dset) - self.dict_domain_class_count[key] = dict_class_count - for key, dset in self.dict_dset_te.items(): - dict_class_count = self._count_class_one_hot(dset) - self.dict_domain_class_count[key] = dict_class_count
- - def _count_class_one_hot(self, dset): - labels_count = torch.zeros(self.dim_y, dtype=torch.long) - for _, target, *_ in dset: - labels_count += target.long() - - list_count = list(labels_count.cpu().numpy()) - dict_class_count = {} - for name, count in zip(self.list_str_y, list_count): - dict_class_count[name] = count - return dict_class_count - - def _count_class(self, dset): # @FIXME: remove this - labels = dset.targets - class_dict = dict(Counter(labels)) - return class_dict
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/task_folder.html b/docs/build/html/_modules/domainlab/tasks/task_folder.html deleted file mode 100644 index 48f86f883..000000000 --- a/docs/build/html/_modules/domainlab/tasks/task_folder.html +++ /dev/null @@ -1,413 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.task_folder — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.task_folder

-"""
-When class names and numbers does not match across different domains
-"""
-from torchvision import transforms
-
-from domainlab.dsets.dset_subfolder import DsetSubFolder
-from domainlab.dsets.utils_data import (DsetInMemDecorator,
-                                        fun_img_path_loader_default,
-                                        mk_fun_label2onehot)
-from domainlab.tasks.b_task import NodeTaskDict
-from domainlab.tasks.utils_task import DsetClassVecDecoratorImgPath
-
-
-
[docs]class NodeTaskFolder(NodeTaskDict): - """ - create dataset by loading files from an organized folder - then each domain correspond to one dataset - """ - @property - def dict_domain2imgroot(self): - """ - {"domain name":"xx/yy/zz"} - """ - return self._dict_domains2imgroot - - @dict_domain2imgroot.setter - def dict_domain2imgroot(self, dict_root): - """ - {"domain name":"xx/yy/zz"} - """ - if not isinstance(dict_root, dict): - raise RuntimeError("input is not diciontary") - self._dict_domains2imgroot = dict_root - - @property - def extensions(self): - """ - return allowed extensions - """ - return self.dict_att["img_extensions"] - - @extensions.setter - def extensions(self, str_format): - self.dict_att["img_extensions"] = str_format - -
[docs] def get_dset_by_domain(self, args, na_domain, split=False): - if float(args.split): - raise RuntimeError( - "this task does not support spliting training domain yet") - if self._dict_domain_img_trans: - trans = self._dict_domain_img_trans[na_domain] - if na_domain not in self.list_domain_tr: - trans = self.img_trans_te - else: - trans = transforms.ToTensor() - dset = DsetSubFolder(root=self.dict_domain2imgroot[na_domain], - list_class_dir=self.list_str_y, - loader=fun_img_path_loader_default, - extensions=self.extensions, - transform=trans, - target_transform=mk_fun_label2onehot(len(self.list_str_y))) - return dset, dset # @FIXME: validation by default set to be training set
- - -
[docs]class NodeTaskFolderClassNaMismatch(NodeTaskFolder): - """ - when the folder names of the same class from different domains have - different names - """ -
[docs] def get_dset_by_domain(self, args, na_domain, split=False): - if float(args.split): - raise RuntimeError( - "this task does not support spliting training domain yet") - print("reading domain:", na_domain) - domain_class_dirs = \ - self._dict_domain_folder_name2class[na_domain].keys() - if self._dict_domain_img_trans: - trans = self._dict_domain_img_trans[na_domain] - if na_domain not in self.list_domain_tr: - trans = self.img_trans_te - else: - trans = transforms.ToTensor() - - ext = None if self.extensions is None else self.extensions[na_domain] - dset = DsetSubFolder(root=self.dict_domain2imgroot[na_domain], - list_class_dir=list(domain_class_dirs), - loader=fun_img_path_loader_default, - extensions=ext, - transform=trans, - target_transform=mk_fun_label2onehot( - len(self.list_str_y))) - # dset.path2imgs - dict_folder_name2class_global = \ - self._dict_domain_folder_name2class[na_domain] - dset = DsetClassVecDecoratorImgPath( - dset, dict_folder_name2class_global, self.list_str_y) - # Always use the DsetInMemDecorator at the last step - # since it does not have other needed attributes in bewteen - if args.dmem: - dset = DsetInMemDecorator(dset, na_domain) - return dset, dset # @FIXME: validation by default set to be training set
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/task_folder_mk.html b/docs/build/html/_modules/domainlab/tasks/task_folder_mk.html deleted file mode 100644 index b656e0a29..000000000 --- a/docs/build/html/_modules/domainlab/tasks/task_folder_mk.html +++ /dev/null @@ -1,372 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.task_folder_mk — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.task_folder_mk

-"""
-When class names and numbers does not match across different domains
-"""
-from domainlab.tasks.task_folder import NodeTaskFolderClassNaMismatch
-
-
-
[docs]def mk_task_folder(extensions, - list_str_y, - dict_domain_folder_name2class, - dict_domain_img_trans, - img_trans_te, - isize, - dict_domain2imgroot, - taskna, - succ=None): - """ - Make task by specifying each domain with folder structures - :param extensions: Different Options: 1. a python dictionary with key as the domain name - and value (str or tuple[str]) as the file extensions of the image. 2. a str or tuple[str] - with file extensions for all domains. 3. None: in each domain all files with an extension - in ('jpg', 'jpeg', 'png') are loaded. - :param list_str_y: a python list with user defined class name where - the order of the list matters. - :param dict_domain_folder_name2class: a python dictionary, with key - as the user specified domain name, value as a dictionary to map the - sub-folder name of each domain's class folder into the user defined - common class name. - :param dict_domain_img_trans: a python dictionary with keys as the user - specified domain name, value as a user defined torchvision transform. - This feature allows carrying out different transformation (composition) to different - domains at training time. - :param img_trans_te: at test or inference time, we do not have knowledge - of domain information so only a unique transform (composition) is allowed. - :isize: domainlab.tasks.ImSize(image channel, image height, image width) - :dict_domain2imgroot: a python dictionary with keys as user specified domain - names and values as the absolute path to each domain's data. - :taskna: user defined task name - """ - class NodeTaskFolderDummy(NodeTaskFolderClassNaMismatch): - @property - def task_name(self): - """ - The basic name of the task, without configurations - """ - return taskna - - def conf(self, args): - self.extensions = extensions - self.list_str_y = list_str_y - self._dict_domain_folder_name2class = dict_domain_folder_name2class - self.isize = isize - self.set_list_domains(list(self._dict_domain_folder_name2class.keys())) - self.dict_domain2imgroot = dict_domain2imgroot - self._dict_domain_img_trans = dict_domain_img_trans - self.img_trans_te = img_trans_te - - def init_business(self, args): - self.conf(args) - super().init_business(args) - return NodeTaskFolderDummy(succ=succ)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/task_mnist_color.html b/docs/build/html/_modules/domainlab/tasks/task_mnist_color.html deleted file mode 100644 index c26d85169..000000000 --- a/docs/build/html/_modules/domainlab/tasks/task_mnist_color.html +++ /dev/null @@ -1,374 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.task_mnist_color — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.task_mnist_color

-"""
-Color MNIST with palette
-"""
-from torch.utils.data import random_split
-
-from domainlab.dsets.dset_mnist_color_solo_default import \
-    DsetMNISTColorSoloDefault
-from domainlab.dsets.utils_color_palette import default_rgb_palette  # @FIXME
-from domainlab.tasks.b_task import NodeTaskDict
-from domainlab.tasks.utils_task import ImSize
-from domainlab.utils.utils_classif import mk_dummy_label_list_str
-
-
-
[docs]class NodeTaskMNISTColor10(NodeTaskDict): - """ - Use the deafult palette with 10 colors - """ - @property - def list_str_y(self): - return mk_dummy_label_list_str("digit", 10) - - @property - def isize(self): - """image channel, height, width""" - return ImSize(3, 28, 28) - -
[docs] def get_list_domains(self): - """ - 1. get list of domain names - 2. better use method than property so new domains can be added - """ - list_domains = [] - for rgb_list in default_rgb_palette: # 10 colors - domain = "_".join([str(c) for c in rgb_list]) - domain = "rgb_" + domain - list_domains.append(domain) - return list_domains
- -
[docs] def get_dset_by_domain(self, args, na_domain, split=True): # @FIXME: different number of arguments than parent - """get_dset_by_domain. - :param args: - :param na_domain: - :param split: for test set, no need to split - args.split: by default, split is set to be zero which in python can - be evaluated in if statement, in which case, no validation set will be - created. Otherwise, this argument is the split ratio - """ - ratio_split = float(args.split) if split else False - # by default, split is set to be zero which in python can - # be evaluated in if statement, in which case, no validation - # set will be created. Otherwise, this argument is - # the split ratio - ind_global = self.get_list_domains().index(na_domain) - dset = DsetMNISTColorSoloDefault(ind_global, args.dpath) - train_set = dset - val_set = dset - # split dset into training and test - if ratio_split: - train_len = int(len(dset) * ratio_split) - val_len = len(dset) - train_len - train_set, val_set = random_split(dset, [train_len, val_len]) - return train_set, val_set
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/task_pathlist.html b/docs/build/html/_modules/domainlab/tasks/task_pathlist.html deleted file mode 100644 index 23f391792..000000000 --- a/docs/build/html/_modules/domainlab/tasks/task_pathlist.html +++ /dev/null @@ -1,430 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.task_pathlist — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.task_pathlist

-"""
-The class TaskPathList provides the user an interface to provide a file with
-each line consisting of a pair, where the first slot contains the path
-(either absolute or relative if the user knows from where this package is
-executed)
-of an image and the second slot contains the class label as a numerical string.
-"""
-import os
-
-import torch.multiprocessing
-
-torch.multiprocessing.set_sharing_strategy('file_system')
-# "too many opened files" https://github.com/pytorch/pytorch/issues/11201
-
-from torchvision import transforms
-
-from domainlab.dsets.dset_img_path_list import DsetImPathList
-from domainlab.dsets.utils_data import mk_fun_label2onehot
-from domainlab.tasks.b_task import NodeTaskDict
-
-
-
[docs]class NodeTaskPathListDummy(NodeTaskDict): - pass
- - -
[docs]def mk_node_task_path_list(isize, - list_str_y, - trans4all, - dict_class_label2name, - dict_domain2imgroot, - dict_d2filepath_list_img, - dict_d2filepath_list_img_val, - dict_d2filepath_list_img_te, - succ=None): - """mk_node_task_path_list. - - :param isize: - :param list_str_y: - :param trans4all: - :param dict_class_label2name: - :param dict_domain2imgroot: - :param dict_d2filepath_list_img: - :param dict_d2filepath_list_img_val: - :param dict_d2filepath_list_img_te: - :param succ: - """ - class NodeTaskPathList(NodeTaskPathListDummy): - """ - The class TaskPathList provides the user an interface to provide a file - with each line consisting of a pair separated by comma, where the - first slot contains the path (either absolute or relative if the user - knows from where this package is executed) of an image and the second - slot contains the class label as a numerical string. - e.g.: /path/2/file/art_painting/dog/pic_376.jpg 1 - """ - def _get_complete_domain(self, na_domain, list_domain_path): - """_get_complete_domain. - - :param na_domain: - """ - if self._dict_domain_img_trans: - trans = self._dict_domain_img_trans[na_domain] - else: - trans = trans4all - root_img = self.dict_domain2imgroot[na_domain] - path2filelist = list_domain_path[na_domain] - path2filelist = os.path.expanduser(path2filelist) - root_img = os.path.expanduser(root_img) - dset = DsetImPathList(root_img, path2filelist, trans_img=trans, - trans_target=mk_fun_label2onehot( - len(self.list_str_y))) - return dset - - def get_dset_by_domain(self, args, na_domain, split=True): - """get_dset_by_domain. - - :param args: - :param na_domain: - :param split: for test set, use the whole - """ - if not split: # no train/val split for test domain - dset = self._get_complete_domain( - na_domain, - self._dict_domain2filepath_list_im_te) - return dset, dset # @FIXME: avoid returning two identical - - dset = self._get_complete_domain( - na_domain, - self._dict_domain2filepath_list_im) - - dset_val = self._get_complete_domain( - na_domain, - self._dict_domain2filepath_list_im_val) - - return dset, dset_val - - def conf(self, args): - """conf. - - :param args: - """ - self.list_str_y = list_str_y - self.isize = isize - self.dict_domain2imgroot = dict_domain2imgroot - self._dict_domain2filepath_list_im = dict_d2filepath_list_img - self._dict_domain2filepath_list_im_val = dict_d2filepath_list_img_val - self._dict_domain2filepath_list_im_te = dict_d2filepath_list_img_te - self.set_list_domains(list(self.dict_domain2imgroot.keys())) - - def init_business(self, args): - """init_business. - - :param args: - """ - self.conf(args) - super().init_business(args) - - return NodeTaskPathList(succ)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/task_utils.html b/docs/build/html/_modules/domainlab/tasks/task_utils.html deleted file mode 100644 index 6f895ccf5..000000000 --- a/docs/build/html/_modules/domainlab/tasks/task_utils.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.task_utils — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.task_utils

-"""
-convert ids to a list of domain names
-"""
-
-
-
[docs]def parse_domain_id(list_domain_id, list_domains): - """ - Convert ids to a list of domain names. - :param list_domain_id: domain id or ids provided as an int or str, - or a list of int or str. - :param list_domains: list of available domains - :return: list of domain names - """ - if not isinstance(list_domain_id, list): - list_domain_id = [list_domain_id] - list_domains_subset = [] - for ele in list_domain_id: - if isinstance(ele, int): - list_domains_subset.append(list_domains[ele]) - elif isinstance(ele, str): - if ele.isdigit(): - list_domains_subset.append(list_domains[int(ele)]) - else: - list_domains_subset.append(ele) - else: - raise RuntimeError("domain ids should be either int or str") - return list_domains_subset
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/utils_task.html b/docs/build/html/_modules/domainlab/tasks/utils_task.html deleted file mode 100644 index 663801bd8..000000000 --- a/docs/build/html/_modules/domainlab/tasks/utils_task.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.utils_task — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.utils_task

-"""
-Task wraps around datasets, this file provide utilities
-"""
-import os
-from pathlib import Path
-
-import numpy
-import torch
-import torchvision
-from torch.utils.data import Dataset
-
-from domainlab.utils.utils_class import store_args
-
-
-
[docs]class ImSize(): - """ImSize.""" - - @store_args - def __init__(self, i_c, i_h, i_w): - """ - store channel, height, width - """ - @property - def c(self): - """image channel""" - return self.i_c - - @property - def h(self): - """image height""" - return self.i_h - - @property - def w(self): - """image width""" - return self.i_w
- - -
[docs]def mk_onehot(dim, ind): - """ - :param dim: dimension of representation vector - :param ind: index - """ - eye = torch.eye(dim) - vec = eye[ind] - return vec
- - -
[docs]def mk_loader(dset, bsize, drop_last=True, shuffle=True): - """ - :param bs: batch size - """ - if len(dset) < bsize: - bsize = len(dset) - loader = torch.utils.data.DataLoader( - dataset=dset, - batch_size=bsize, - shuffle=shuffle, - # shuffle must be true so the last incomplete - # batch get used in anohter epoch - num_workers=int(0), # @FIXME: - drop_last=drop_last) - return loader
- - -
[docs]class DsetDomainVecDecorator(Dataset): - """ - decorate a pytorch dataset with a fixed vector representation of domain - """ - def __init__(self, dset, vec_domain, na_domain): - """ - :param dset: x, y - :param vec_domain: vector representation of domain - :param na_domain: string description of domain - """ - self.dset = dset - self.vec_domain = vec_domain - self.na_domain = na_domain - - @property - def targets(self): - """ - return a list of all targets so class sample count is straight forward - """ - return self.dset.targets - - def __getitem__(self, idx): - """ - :param idx: - """ - tensor, vec_class, *other_vars = self.dset.__getitem__(idx) - if other_vars: - return (tensor, vec_class, self.vec_domain, *other_vars) - return tensor, vec_class, self.vec_domain - - def __len__(self): - """__len__.""" - return self.dset.__len__()
- - -
[docs]class DsetDomainVecDecoratorImgPath(DsetDomainVecDecorator): - """ - Except returning x, y, d, additionally, the path of x is - returned currently not in use since it is mostly important - to print predictions together with path for the test domain - """ - def __getitem__(self, idx): - """ - :param idx: - """ - tensor, vec_class, path = self.dset.__getitem__(idx) - return tensor, vec_class, self.vec_domain, path
- - -
[docs]class DsetClassVecDecorator(Dataset): - """ - decorate a pytorch dataset with a new class name - """ - def __init__(self, dset, dict_folder_name2class_global, list_str_y): - """ - :param dset: x, y, *d - :param dict_folder2class: dictionary that maps - class folder of domain to glbal class - """ - self.dset = dset - self.class2idx = {k:v for (k,v) in self.dset.class_to_idx.items() \ - if k in self.dset.list_class_dir} - assert self.class2idx - self.dict_folder_name2class_global = dict_folder_name2class_global - self.list_str_y = list_str_y - # inverst key:value to value:key for backward map - self.dict_old_idx2old_class = dict((v, k) for k, v in self.class2idx.items()) - dict_class_na_local2vec_new = dict( - (k, self.fun_class_local_na2vec_new(k)) for k, v in self.class2idx.items()) - self.dict_class_na_local2vec_new = dict_class_na_local2vec_new - - @property - def targets(self): - """ - return a list of all targets so class sample count is straight forward - """ - return self.dset.targets - -
[docs] def fun_class_local_na2vec_new(self, k): - """ - local class name within one domain, to one-hot - vector of new representation - """ - ind = self.list_str_y.index(self.dict_folder_name2class_global[k]) - return mk_onehot(len(self.list_str_y), ind)
- - def __getitem__(self, idx): - """ - :param idx: - """ - tensor, vec_class, *other_vars = self.dset.__getitem__(idx) - vec_class = vec_class.numpy() - ind_old = numpy.argmax(vec_class) - class_local = self.dict_old_idx2old_class[ind_old] - vec_class_new = self.dict_class_na_local2vec_new[class_local] - return tensor, vec_class_new, *other_vars - - def __len__(self): - """__len__.""" - return self.dset.__len__()
- - -
[docs]class DsetClassVecDecoratorImgPath(DsetClassVecDecorator): - def __getitem__(self, idx): - """ - :param idx: - This function is mainly - """ - tensor, vec_class_new, path = super().__getitem__(idx) - return tensor, vec_class_new, path[0]
- - -
[docs]class LoaderDomainLabel(): - """ - wraps a dataset with domain label and into a loader - """ - def __init__(self, batch_size, dim_d): - """__init__. - - :param batch_size: - :param dim_d: - """ - self.batch_size = batch_size - self.dim_d = dim_d - - def __call__(self, dset, d_ind, na_domain): - """ - wrap_dataset2loader_with_domain_label. - :param dataset: - :param batch_size: - :param d_dim: - :param d_ind: - """ - d_eye = torch.eye(self.dim_d) - d_label = d_eye[d_ind] - dset = DsetDomainVecDecorator(dset, d_label, na_domain) - loader = mk_loader(dset, self.batch_size) - return loader
- - -
[docs]def tensor1hot2ind(tensor_label): - """tensor1hot2ind. - - :param tensor_label: - """ - _, label_ind = torch.max(tensor_label, dim=1) - npa_label_ind = label_ind.numpy() - return npa_label_ind
- -# @FIXME: this function couples strongly with the task, -# should be a class method of task -
[docs]def img_loader2dir(loader, - folder, - test=False, - list_domain_na=None, - list_class_na=None, - batches=5): - """ - save images from loader to directory so speculate if loader is correct - :param loader: pytorch data loader - :param folder: folder to save images - :param test: if true, the loader is assumend to be a test loader; if false (default) it is assumed to be a train loader - :param list_domain_na: optional list of domain names - :param list_class_na: optional list of class names - :param batches: number of batches to save - """ - Path(os.path.normpath(folder)).mkdir(parents=True, exist_ok=True) - l_iter = iter(loader) - counter = 0 - batches = min(batches, len(l_iter)) - for _ in range(batches): - img, vec_y, *other_vars = next(l_iter) - class_label_ind_batch = tensor1hot2ind(vec_y) - - # get domain label - # Note 1: test loaders don't return domain labels (see NodeTaskDict.init_business) - # Note 2: for train loaders domain label will be the 0th element of other_vars (see DsetDomainVecDecorator class above) - has_domain_label_ind = False - if not test: - if other_vars: - domain_label_ind_batch = tensor1hot2ind(other_vars[0]) - has_domain_label_ind = True - - for b_ind in range(img.shape[0]): - class_label_ind = class_label_ind_batch[b_ind] - class_label_scalar = class_label_ind.item() - - if list_class_na is None: - str_class_label = "class_"+str(class_label_scalar) - else: - # @FIXME: where is the correspndance between - # class ind_label and class str_label? - str_class_label = list_class_na[class_label_scalar] - str_domain_label = "unknown" - if has_domain_label_ind: - domain_label_ind = domain_label_ind_batch[b_ind] - if list_domain_na is None: - str_domain_label = str(domain_label_ind) - else: - # @FIXME: the correspondance between - # domain ind_label and domain str_label is missing - str_domain_label = list_domain_na[domain_label_ind] - arr = img[b_ind] - img_vision = torchvision.transforms.ToPILImage()(arr) - f_n = "_".join( - ["class", - str_class_label, - "domain", - str_domain_label, - "n", - str(counter)]) - counter += 1 - path = os.path.join(folder, f_n + ".png") - img_vision.save(path)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/utils_task_dset.html b/docs/build/html/_modules/domainlab/tasks/utils_task_dset.html deleted file mode 100644 index 2755fe87f..000000000 --- a/docs/build/html/_modules/domainlab/tasks/utils_task_dset.html +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.utils_task_dset — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.utils_task_dset

-from torch.utils.data import Dataset
-
-
-
[docs]class DsetIndDecorator4XYD(Dataset): - """ - For dataset of x, y, d, decorate it wih index - """ - def __init__(self, dset): - """ - :param dset: x,y,d - """ - tuple_m = dset[0] - if len(tuple_m) < 3: - raise RuntimeError( - "dataset to be wrapped should output at least x, y, and d; got length ", len(tuple_m)) - self.dset = dset - - def __getitem__(self, index): - """ - :param index: - """ - tensor_x, vec_y, vec_d, *_ = self.dset.__getitem__(index) - return tensor_x, vec_y, vec_d, index - - def __len__(self): - return self.dset.__len__()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/tasks/zoo_tasks.html b/docs/build/html/_modules/domainlab/tasks/zoo_tasks.html deleted file mode 100644 index 2e30788c0..000000000 --- a/docs/build/html/_modules/domainlab/tasks/zoo_tasks.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks.zoo_tasks — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.tasks.zoo_tasks

-import os
-
-from torchvision import transforms
-
-from domainlab.compos.pcr.request import RequestTask
-from domainlab.tasks.task_folder_mk import mk_task_folder
-from domainlab.tasks.task_mnist_color import NodeTaskMNISTColor10
-from domainlab.tasks.utils_task import ImSize
-from domainlab.utils.u_import import import_path
-
-path_this_file = os.path.dirname(os.path.realpath(__file__))
-
-
-
[docs]class TaskChainNodeGetter(object): - """ - 1. Hardcoded chain - 3. Return selected node - """ - def __init__(self, args): - self.args = args - tpath = args.tpath - self.tpath = tpath - self.request = RequestTask(args)() - if tpath is not None: - self.task_module = import_path(self.tpath) - - def __call__(self): - """ - 1. construct the chain, filter out responsible node, create heavy-weight business object - 2. hard code seems to be the best solution - """ - chain = NodeTaskMNISTColor10(None) - - chain = mk_task_folder(extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", - "stuhl": "chair"}, - "sun": {"vehicle": "car", - "sofa": "chair"}, - "labelme": {"drive": "car", - "sit": "chair"} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "sun": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "labelme": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": os.path.join( - path_this_file, - "../../data/vlcs_mini/caltech/"), - "sun": os.path.join( - path_this_file, - "../../data/vlcs_mini/sun/"), - "labelme": os.path.join( - path_this_file, - "../../data/vlcs_mini/labelme/")}, - taskna="mini_vlcs", - succ=chain) - - if self.tpath is not None: - node = self.task_module.get_task(self.args.task) - chain.set_parent(node) - chain = node - if self.args.task is None: - print("") - print("overriding args.task ", - self.args.task, " to ", - node.task_name) - print("") - self.request = node.task_name # @FIXME - node = chain.handle(self.request) - return node
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/flows_gen_img_model.html b/docs/build/html/_modules/domainlab/utils/flows_gen_img_model.html deleted file mode 100644 index 50cdd20ac..000000000 --- a/docs/build/html/_modules/domainlab/utils/flows_gen_img_model.html +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.flows_gen_img_model — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.flows_gen_img_model

-import os
-
-import torch
-
-from domainlab.compos.vae.c_vae_recon import ReconVAEXYD
-from domainlab.utils.utils_img_sav import mk_fun_sav_img
-
-
-
[docs]class FlowGenImgs(): - def __init__(self, model, device): - model = model.to(device) - self.obj_recon = ReconVAEXYD(model) - self.sav_fun = None - - def _save_list(self, recon_list_d, device, img, name): - """ - compare counterfactual - """ - recon_stack_d = torch.cat(recon_list_d) - recon_stack_d = recon_stack_d.to(device) - comparison = torch.cat([img, recon_stack_d]) - self.sav_fun(comparison, name, title=None) # row is actually column here - - def _save_pair(self, x_recon_img, device, img, name): - """ - compare recon and original - """ - x_recon_img = x_recon_img.to(device) - comparison = torch.cat([img, x_recon_img]) - self.sav_fun(comparison, name) - -
[docs] def gen_img_loader(self, loader, device, path, domain): - """ - gen image for the first batch of input loader - """ - for _, (x_batch, y_batch, *d_batch) in enumerate(loader): - x_batch, y_batch = x_batch.to(device), y_batch.to(device) - if d_batch and isinstance(d_batch[0], torch.Tensor): - d_batch = d_batch[0].to(device) - else: - d_batch = None - self.gen_img_xyd(x_batch, y_batch, d_batch, device, path, folder_na=domain) - break
- -
[docs] def gen_img_xyd(self, img, vec_y, vec_d, device, path, folder_na): - img = img.to(device) - vec_y = vec_y.to(device) - if vec_d is not None: - vec_d = vec_d.to(device) - nrow = img.shape[0] # nrow is actually ncol in pytorch save_image!! - self.sav_fun = mk_fun_sav_img(path=path, nrow=nrow, folder_na=folder_na) - self._flow_vanilla(img, vec_y, vec_d, device) - self._flow_cf_y(img, vec_y, vec_d, device) - if vec_d is not None: - self._flow_cf_d(img, vec_y, vec_d, device)
- - def _flow_vanilla(self, img, vec_y, vec_d, device, num_sample=10): - x_recon_img, str_type = self.obj_recon.recon(img) - self._save_pair(x_recon_img, device, img, str_type + '.png') - - x_recon_img, str_type = self.obj_recon.recon(img, vec_y) - self._save_pair(x_recon_img, device, img, str_type + '.png') - - if vec_d is not None: - x_recon_img, str_type = self.obj_recon.recon(img, None, vec_d) - self._save_pair(x_recon_img, device, img, str_type + '.png') - - for i in range(num_sample): - x_recon_img, str_type = self.obj_recon.recon(img, vec_y, vec_d, True, True) - x_recon_img = x_recon_img.to(device) - comparison = torch.cat([img, x_recon_img]) - self.sav_fun(comparison, str_type + str(i) + '.png') - - def _flow_cf_y(self, img, vec_y, vec_d, device): - """ - scan possible values of vec_y - """ - recon_list, str_type = self.obj_recon.recon_cf(img, "y", vec_y.shape[1], device, - zx2fill=None) - self._save_list(recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png") - recon_list, str_type = self.obj_recon.recon_cf(img, "y", vec_y.shape[1], device, zx2fill=0) - self._save_list(recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png") - if vec_d is not None: - recon_list, str_type = self.obj_recon.recon_cf( - img, "y", vec_y.shape[1], device, - vec_d=vec_d, - zx2fill=0) - self._save_list(recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png") - - def _flow_cf_d(self, img, vec_y, vec_d, device): - """ - scan possible values of vec_y - """ - recon_list, str_type = self.obj_recon.recon_cf(img, "d", vec_d.shape[1], device, - zx2fill=None) - self._save_list(recon_list, device, img, "_".join(["recon_cf_d", str_type]) +".png") - recon_list, str_type = self.obj_recon.recon_cf(img, "d", vec_d.shape[1], device, zx2fill=0) - self._save_list(recon_list, device, img, "_".join(["recon_cf_d", str_type]) +".png")
- - -
[docs]def fun_gen(model, device, node, args, subfolder_na, output_folder_na="gen"): - flow = FlowGenImgs(model, device) - path = os.path.join(args.out, output_folder_na, node.task_name, args.aname, subfolder_na) - flow.gen_img_loader(node.loader_te, device, - path=path, - domain="_".join(args.te_d)) - flow.gen_img_loader(node.loader_tr, device, - path=path, - domain="_".join(node.list_domain_tr))
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/generate_benchmark_plots.html b/docs/build/html/_modules/domainlab/utils/generate_benchmark_plots.html deleted file mode 100644 index 407abc202..000000000 --- a/docs/build/html/_modules/domainlab/utils/generate_benchmark_plots.html +++ /dev/null @@ -1,610 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.generate_benchmark_plots — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.generate_benchmark_plots

-'''
-generate the benchmark plots by calling the gen_bencmark_plots(...) function
-'''
-import os
-from ast import literal_eval   # literal_eval can safe evaluate python expression
-import matplotlib.pyplot as plt
-import matplotlib
-import pandas as pd
-import seaborn as sns
-import numpy as np
-
-matplotlib.use('Agg')
-
-COLNAME_ALGO = "algo"
-COLNAME_PARAM = "params"
-
-
-
[docs]def gen_benchmark_plots(agg_results: str, output_dir: str): - ''' - generate the benchmark plots from a csv file containing the aggregated restults. - The csv file must have the columns: - [param_index, task, algo, epos, te_d, seed, params, ...] - all columns after seed are intrepreted as objectives of the results, they can e.g. - be acc, precision, recall, specificity, f1, auroc. - - agg_results: path to the csv file - output_dir: path to a folder which shall contain the results - ''' - raw_df = pd.read_csv(agg_results, index_col=False, - converters={COLNAME_PARAM: literal_eval}, - # literal_eval can safe evaluate python expression - skipinitialspace=True) - raw_df[COLNAME_PARAM] = round_vals_in_dict(raw_df[COLNAME_PARAM]) - # crop param_index and task from the dataframe - dataframe = raw_df.iloc[:, 2:] # @FIXME: hard coded - # generating plot - gen_plots(dataframe, output_dir)
- - -
[docs]def round_vals_in_dict(df_column_in): - ''' - replaces the dictionary by a string containing only the significant digits of the hyperparams - df_column_in: columns of the dataframe containing the dictionary of hyperparams - ''' - df_column = df_column_in.copy() - df_column_out = df_column_in.copy() - for i in range(df_column.shape[0]): - string = '' - for num, val in enumerate(list(df_column[i].values())): - key = list(df_column[i].keys())[num] - val = np.format_float_scientific(val, precision=1, unique=False, trim='0') - string += str(key) + ': ' + str(val) + ', ' - df_column_out[i] = string[:-2] - return df_column_out
- - -
[docs]def gen_plots(dataframe: pd.DataFrame, output_dir: str): - ''' - dataframe: dataframe with columns - [' algo', ' epos', ' te_d', ' seed', ' params', ' acc', ' precision', ... ] - ''' - os.makedirs(output_dir, exist_ok=True) - # scatterplot matrices - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix_reg.png', - reg=True, distinguish_param_setups=False) - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix.png', - reg=False, distinguish_param_setups=False) - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix_dist_reg.png', - reg=True, distinguish_param_setups=True) - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix_dist.png', - reg=False, distinguish_param_setups=True) - - # radar plots - radar_plot(dataframe, file=output_dir + '/radar_dist.png', distinguish_hyperparam=True) - radar_plot(dataframe, file=output_dir + '/radar.png', distinguish_hyperparam=False) - - # scatter plots for parirs of objectives - os.makedirs(output_dir + '/scatterpl', exist_ok=True) - obj = dataframe.columns[5:] - for i, obj_i in enumerate(obj): - for j in range(i+1, len(obj)): - try: - scatterplot(dataframe, [obj_i, obj[j]], - file=output_dir + '/scatterpl/' + obj_i + '_' + obj[j] + '.png') - except IndexError: - print(f'WARNING: disabling kde because cov matrix is singular for objectives ' - f'{obj_i} & {obj[j]}') - scatterplot(dataframe, [obj_i, obj[j]], - file=output_dir + '/scatterpl/' + obj_i + '_' + obj[j] + '.png', - kde=False) - - # create plots for the different algortihms - for algorithm in dataframe[COLNAME_ALGO].unique(): - os.makedirs(output_dir + '/' + str(algorithm), exist_ok=True) - dataframe_algo = dataframe[dataframe[COLNAME_ALGO] == algorithm] - - # scatterplot matrices - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix_reg.png', - reg=True, distinguish_param_setups=False) - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix.png', - reg=False, distinguish_param_setups=False) - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix_dist_reg.png', - reg=True, distinguish_param_setups=True) - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix_dist.png', - reg=False, distinguish_param_setups=True) - - # radar plots - radar_plot(dataframe_algo, file=output_dir + '/' + str(algorithm) + '/radar_dist.png', - distinguish_hyperparam=True) - radar_plot(dataframe_algo, file=output_dir + '/' + str(algorithm) + '/radar.png', - distinguish_hyperparam=False) - - # scatter plots for parirs of objectives - os.makedirs(output_dir + '/' + str(algorithm) + '/scatterpl', exist_ok=True) - obj = dataframe_algo.columns[5:] - for i, obj_i in enumerate(obj): - for j in range(i + 1, len(obj)): - try: - scatterplot(dataframe_algo, [obj_i, obj[j]], - file=output_dir + '/' + str(algorithm) + - '/scatterpl/' + obj_i + '_' + obj[j] + '.png', - distinguish_hyperparam=True) - except IndexError: - print(f'WARNING: disabling kde because cov matrix is singular for objectives ' - f'{obj_i} & {obj[j]}') - scatterplot(dataframe_algo, [obj_i, obj[j]], - file=output_dir + '/' + str(algorithm) + - '/scatterpl/' + obj_i + '_' + obj[j] + '.png', - kde=False, - distinguish_hyperparam=True)
- - -
[docs]def scatterplot_matrix(dataframe_in, file=None, reg=True, distinguish_param_setups=True): - ''' - dataframe: dataframe containing the data with columns - [algo, epos, te_d, seed, params, obj1, ..., obj2] - file: filename to save the plots (if None, the plot will not be saved) - reg: if True a regression line will be plotted over the data - distinguish_param_setups: if True the plot will not only distinguish between models, - but also between the parameter setups - ''' - dataframe = dataframe_in.copy() - index = list(range(5, dataframe.shape[1])) - if distinguish_param_setups: - dataframe_ = dataframe.iloc[:, index] - dataframe_.insert(0, 'label', - dataframe[COLNAME_ALGO].astype(str) + ', ' + - dataframe[COLNAME_PARAM].astype(str)) - else: - index_ = list(range(5, dataframe.shape[1])) - index_.insert(0, 0) - dataframe_ = dataframe.iloc[:, index_] - - if reg: - if not distinguish_param_setups: - g_p = sns.pairplot(data=dataframe_, hue=COLNAME_ALGO, corner=True, kind='reg') - else: - g_p = sns.pairplot(data=dataframe_, hue='label', corner=True, kind='reg') - else: - if not distinguish_param_setups: - g_p = sns.pairplot(data=dataframe_, hue=COLNAME_ALGO, corner=True) - else: - g_p = sns.pairplot(data=dataframe_, hue='label', corner=True) - - for i in range(len(index)): - for j in range(len(index)): - if i >= j: - g_p.axes[i, j].set_xlim((-0.1, 1.1)) - for k in range(j): - g_p.axes[j, k].set_ylim((-0.1, 1.1)) - - g_p.fig.set_size_inches(12.5, 12) - sns.move_legend(g_p, loc='upper right', bbox_to_anchor=(1., 1.), ncol=1) - plt.tight_layout() - - if file is not None: - plt.savefig(file, dpi=300)
- - -
[docs]def scatterplot(dataframe_in, obj, file=None, kde=True, distinguish_hyperparam=False): - ''' - dataframe: dataframe containing the data with columns - [algo, epos, te_d, seed, params, obj1, ..., obj2] - obj1 & obj2: name of the objectives which shall be plotted against each other - file: filename to save the plots (if None, the plot will not be saved) - kde: if True the distribution of the points will be estimated and plotted as kde plot - distinguish_param_setups: if True the plot will not only distinguish between models, - but also between the parameter setups - ''' - obj1, obj2 = obj - - dataframe = dataframe_in.copy() - dataframe[COLNAME_PARAM] = dataframe[COLNAME_PARAM].astype(str) - - if distinguish_hyperparam: - if kde: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1), kind='kde', - zorder=0, levels=8, alpha=0.35, warn_singular=False) - gg_p = sns.scatterplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, - ax=g_p.ax_joint) - else: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1)) - gg_p = g_p.ax_joint - else: - if kde: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_ALGO, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1), kind='kde', - zorder=0, levels=8, alpha=0.35, warn_singular=False) - gg_p = sns.scatterplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_ALGO, - style=COLNAME_PARAM, - ax=g_p.ax_joint) - else: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_ALGO, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1)) - gg_p = sns.scatterplot(data=dataframe, x=obj1, y=obj2, style=COLNAME_PARAM, - ax=g_p.ax_joint) - - gg_p.set_aspect('equal') - gg_p.legend(fontsize=6, loc='best') - - if file is not None: - plt.savefig(file, dpi=300)
- - -
[docs]def max_0_x(x_arg): - ''' - max(0, x_arg) - ''' - return max(0, x_arg)
- - -
[docs]def radar_plot(dataframe_in, file=None, distinguish_hyperparam=True): - ''' - dataframe_in: dataframe containing the data with columns - [algo, epos, te_d, seed, params, obj1, ..., obj2] - file: filename to save the plots (if None, the plot will not be saved) - distinguish_param_setups: if True the plot will not only distinguish between models, - but also between the parameter setups - ''' - dataframe = dataframe_in.copy() - if distinguish_hyperparam: - dataframe.insert(0, 'label', - dataframe[COLNAME_ALGO].astype(str) + ', ' + - dataframe[COLNAME_PARAM].astype(str)) - else: - dataframe.insert(0, 'label', dataframe[COLNAME_ALGO]) - index = list(range(6, dataframe.shape[1])) - num_lines = len(dataframe['label'].unique()) - _, axis = plt.subplots(figsize=(9, 9 + (0.28 * num_lines)), subplot_kw=dict(polar=True)) - num = 0 - - # Split the circle into even parts and save the angles - # so we know where to put each axis. - angles = list(np.linspace(0, 2 * np.pi, len(dataframe.columns[index]), endpoint=False)) - for algo_name in dataframe['label'].unique(): - mean = dataframe.loc[dataframe['label'] == algo_name].iloc[:, index].mean().to_list() - std = dataframe.loc[dataframe['label'] == algo_name].iloc[:, index].std().to_list() - - angles_ = angles - # The plot is a circle, so we need to "complete the loop" - # and append the start value to the end. - mean = np.array(mean + mean[:1]) - std = np.array(std + std[:1]) - angles_ = np.array(angles_ + angles_[:1]) - - # Draw the outline of the data. - axis.plot(angles_, mean, - color=list(plt.rcParams["axes.prop_cycle"])[num]['color'], - linewidth=2, label=algo_name) - - # Fill it in. - axis.fill_between(angles_, list(map(max_0_x, mean - std)), - y2=mean + std, - color=list(plt.rcParams["axes.prop_cycle"])[num]['color'], - alpha=0.1) - num += 1 - num = num % len(list(plt.rcParams["axes.prop_cycle"])) - - # Fix axis to go in the right order and start at 12 o'clock. - axis.set_theta_offset(np.pi / 2) - axis.set_theta_direction(-1) - - # Draw axis lines for each angle and label. - axis.set_thetagrids(np.degrees(angles), dataframe.columns[index]) - - axis.set_ylim((0, 1)) - - plt.legend(loc='lower right', bbox_to_anchor=(1., 1.035), - ncol=1, fontsize=10) - - if file is not None: - plt.savefig(file, dpi=300)
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/get_git_tag.html b/docs/build/html/_modules/domainlab/utils/get_git_tag.html deleted file mode 100644 index 6667a39bd..000000000 --- a/docs/build/html/_modules/domainlab/utils/get_git_tag.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.get_git_tag — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.get_git_tag

-import subprocess
-import warnings
-from subprocess import CalledProcessError
-
-
-
[docs]def get_git_tag(print_diff=False): - flag_not_commited = False - try: - subprocess.check_output( - ['git', 'diff-index', '--quiet', 'HEAD']) - except CalledProcessError: - print("\n\n") - warnings.warn("!!!: not committed yet") - flag_not_commited = True - print("\n\n") - try: - diff_byte = subprocess.check_output(['git', 'diff']) - if print_diff: - print(diff_byte) # print is currently ugly, do not use! - except Exception: - warnings.warn("not in a git repository") - try: - tag_byte = subprocess.check_output( - ["git", "describe", "--always"]).strip() - print(tag_byte) - tag_str = str(tag_byte) - git_str = tag_str.replace("'", "") - if flag_not_commited: - git_str = git_str + "_not_commited" - return git_str - except Exception: - warnings.warn("not in a git repository") - return "no_git_version"
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/hyperparameter_sampling.html b/docs/build/html/_modules/domainlab/utils/hyperparameter_sampling.html deleted file mode 100644 index fbb6f78c1..000000000 --- a/docs/build/html/_modules/domainlab/utils/hyperparameter_sampling.html +++ /dev/null @@ -1,577 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.hyperparameter_sampling — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.hyperparameter_sampling

-"""
-Samples the hyperparameters according to a benchmark configuration file.
-"""
-import os
-from pydoc import locate
-from typing import List
-from ast import literal_eval   # literal_eval can safe evaluate python expression
-
-import numpy as np
-import pandas as pd
-
-
-
[docs]class Hyperparameter: - """ - Represents a hyperparameter. - The datatype of .val is int if step and p1 is integer valued, - else float. - - p1: min or mean - p2: max or scale - reference: None or name of referenced hyperparameter - """ - def __init__(self, name: str): - self.name = name - self.val = 0 - - def _ensure_step(self): - """Make sure that the hyperparameter sticks to the discrete grid""" - raise NotImplementedError - -
[docs] def sample(self): - """Sample this parameter, respecting properties""" - raise NotImplementedError
- -
[docs] def get_val(self): - """Returns the current value of the hyperparameter""" - return self.val
- -
[docs] def datatype(self): - """ - Returns the datatype of this parameter. - This does not apply for references. - """ - raise NotImplementedError
- - -
[docs]class SampledHyperparameter(Hyperparameter): - """ - A numeric hyperparameter that shall be sampled - """ - def __init__(self, name: str, config: dict): - super().__init__(name) - self.step = config.get('step', 0) - try: - self.distribution = config['distribution'] - if self.distribution in {'uniform', 'loguniform'}: - self.p_1 = config['min'] - self.p_2 = config['max'] - elif self.distribution in {'normal', 'lognormal'}: - self.p_1 = config['mean'] - self.p_2 = config['std'] - else: - raise RuntimeError(f"Unsupported distribution type: {self.distribution}.") - except KeyError as ex: - raise RuntimeError(f"Missing required key for parameter {name}.") from ex - - self.p_1 = float(self.p_1) - self.p_2 = float(self.p_2) - - def _ensure_step(self): - """Make sure that the hyperparameter sticks to the discrete grid""" - if self.step == 0: - return # continous parameter - - # round to next discrete value. - off = (self.val - self.p_1) % self.step - if off < self.step / 2: - self.val -= off - else: - self.val += self.step - off - # ensure correct datatype - if self.datatype() == int: - self.val = self.datatype()(np.round(self.val)) - -
[docs] def sample(self): - """Sample this parameter, respecting properties""" - if self.distribution == 'uniform': - self.val = np.random.uniform(self.p_1, self.p_2) - elif self.distribution == 'loguniform': - self.val = 10 ** np.random.uniform(np.log10(self.p_1), np.log10(self.p_2)) - elif self.distribution == 'normal': - self.val = np.random.normal(self.p_1, self.p_2) - elif self.distribution == 'lognormal': - self.val = 10 ** np.random.normal(self.p_1, self.p_2) - else: - raise RuntimeError(f"Unsupported distribution type: {self.distribution}.") - self._ensure_step()
- -
[docs] def datatype(self): - return int if self.step % 1 == 0 and self.p_1 % 1 == 0 else float
- - -
[docs]class ReferenceHyperparameter(Hyperparameter): - """ - Hyperparameter that references only a different one. - Thus, this parameter is not sampled but set after sampling. - """ - def __init__(self, name: str, config: dict): - super().__init__(name) - self.reference = config.get('reference', None) - - def _ensure_step(self): - """Make sure that the hyperparameter sticks to the discrete grid""" - # nothing to do for references - return - -
[docs] def sample(self): - """Sample this parameter, respecting properties""" - # nothing to do for references - return
- -
[docs] def datatype(self): - raise RuntimeError("Datatype unknown for ReferenceHyperparameter")
- - -
[docs]class CategoricalHyperparameter(Hyperparameter): - """ - A sampled hyperparameter, which is constraint to fixed, - user given values and datatype - """ - def __init__(self, name: str, config: dict): - super().__init__(name) - self.allowed_values = config['values'] - self.type = locate(config['datatype']) - self.allowed_values = [self.type(v) for v in self.allowed_values] - - def _ensure_step(self): - """Make sure that the hyperparameter sticks to the discrete grid""" - # nothing to do for categorical ones - return - -
[docs] def sample(self): - """Sample this parameter, respecting properties""" - # nothing to do for references - idx = np.random.randint(0, len(self.allowed_values)) - self.val = self.allowed_values[idx]
- -
[docs] def datatype(self): - return self.type
- - -
[docs]def get_hyperparameter(name: str, config: dict) -> Hyperparameter: - """Factory function. Instantiates the correct Hyperparameter""" - if 'reference' in config.keys(): - return ReferenceHyperparameter(name, config) - dist = config.get('distribution', None) - if dist == 'categorical': - return CategoricalHyperparameter(name, config) - - return SampledHyperparameter(name, config)
- - -
[docs]def check_constraints(params: List[Hyperparameter], constraints) -> bool: - """Check if the constraints are fulfilled.""" - # set each param as a local variable - for par in params: - locals().update({par.name: par.val}) - - # set references - for par in params: - if isinstance(par, ReferenceHyperparameter): - try: - setattr(par, 'val', eval(par.reference)) - # NOTE: literal_eval will cause ValueError: malformed node or string - except Exception as ex: - print(f"error in evaluating expression: {par.reference}") - raise ex - locals().update({par.name: par.val}) - - if constraints is None: - return True # shortcut - - # check all constraints - for constr in constraints: - try: - const_res = eval(constr) - # NOTE: literal_eval will cause ValueError: malformed node or string - except SyntaxError as ex: - raise SyntaxError(f"Invalid syntax in yaml config: {constr}") from ex - if not const_res: - return False - - return True
- - -
[docs]def sample_parameters(params: List[Hyperparameter], constraints) -> dict: - """ - Tries to sample from the hyperparameter list. - - Errors if in 10_0000 attempts no sample complying with the - constraints is found. - """ - for _ in range(10_000): - for par in params: - par.sample() - if check_constraints(params, constraints): - samples = {} - for par in params: - samples[par.name] = par.val - return samples - - raise RuntimeError("Could not find an acceptable sample in 10,000 runs." - "Are the bounds and constraints reasonable?")
- - -
[docs]def sample_task(num_samples: int, sample_df: pd.DataFrame, task_name: str, config: dict): - """Sample one task and add it to the dataframe""" - algo = config['aname'] - if 'hyperparameters' in config.keys(): - params = [] - for key, val in config['hyperparameters'].items(): - if key == 'constraints': - continue - params += [get_hyperparameter(key, val)] - - constraints = config['hyperparameters'].get('constraints', None) - for _ in range(num_samples): - sample = sample_parameters(params, constraints) - sample_df.loc[len(sample_df.index)] = [task_name, algo, sample] - else: - # add single line if no varying hyperparameters are specified. - sample_df.loc[len(sample_df.index)] = [task_name, algo, {}]
- - -
[docs]def is_task(val) -> bool: - """Determines if the value of this key is a task.""" - return isinstance(val, dict) and 'aname' in val.keys()
- - -
[docs]def sample_hyperparameters(config: dict, dest: str = None) -> pd.DataFrame: - """ - Samples the hyperparameters according to the given - config, which should be the dictionary of the full - benchmark config yaml. - Result is saved to 'output_dir/hyperparameters.csv' of the - config if not specified explicitly. - - Note: Parts of the yaml content are executed. Thus use this - only with trusted config files. - """ - if dest is None: - dest = config['output_dir'] + os.sep + 'hyperparameters.csv' - - if 'sampling_seed' in config.keys(): - np.random.seed(config['sampling_seed']) - - num_samples = config['num_param_samples'] - samples = pd.DataFrame(columns=['task', 'algo', 'params']) - for key, val in config.items(): - if is_task(val): - sample_task(num_samples, samples, key, val) - - os.makedirs(os.path.dirname(dest), exist_ok=True) - samples.to_csv(dest) - return samples
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/override_interface.html b/docs/build/html/_modules/domainlab/utils/override_interface.html deleted file mode 100644 index 0a69a8cc4..000000000 --- a/docs/build/html/_modules/domainlab/utils/override_interface.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.override_interface — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.override_interface

-
[docs]def override_interface(interface_class): - """overrides. - :param interface_class: the interface class name, always specify this - explicitly as otherwise interface_class is going to be the nearest - function it decorate, and argument "method2override" of returned - function "overrider" accept will be the current child class - - .. code-block:: python - - class BaseClass() - class Child(BaseClass): - @overrides(BaseClass) - def fun(self): - pass - """ - def overrider(method2override): - """overrider. - - :param method: the method to be decorated, method signature will be - returned intactly - """ - assert method2override.__name__ in dir(interface_class) - return method2override - - return overrider
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/perf.html b/docs/build/html/_modules/domainlab/utils/perf.html deleted file mode 100644 index 071932e56..000000000 --- a/docs/build/html/_modules/domainlab/utils/perf.html +++ /dev/null @@ -1,370 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.perf — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.perf

-"""Classification Performance"""
-import torch
-
-
-
[docs]class PerfClassif(): - """Classification Performance""" -
[docs] @classmethod - def gen_fun_acc(cls, dim_target): - """ - :param dim_target: class/domain label embeding dimension - """ - def fun_acc(list_vec_preds, list_vec_labels): - """ - :param list_vec_preds: list of batches - """ - assert len(list_vec_preds) > 0 - correct_count = 0 - obs_count = 0 - for pred, label in zip(list_vec_preds, list_vec_labels): - correct_count += torch.sum(torch.sum(pred == label, dim=1) == dim_target) - obs_count += pred.shape[0] # batch size - if isinstance(correct_count, int): - acc = (correct_count) / obs_count - else: - acc = (correct_count.float()) / obs_count - # AttributeError: 'int' object has no attribute 'float' - # reason: batchsize is too big - return acc - return fun_acc
- -
[docs] @classmethod - def cal_acc(cls, model, loader_te, device, max_batches=None): - """ - :param model: - :param loader_te: - :param device: for final test, GPU can be used - :param max_batches: - maximum number of iteration for data loader, used to - probe performance with less computation burden. - default None, which means to traverse the whole dataset - """ - model.eval() - model_local = model.to(device) - if max_batches is None: - max_batches = len(loader_te) - fun_acc = cls.gen_fun_acc(model_local.dim_y) - list_vec_preds, list_vec_labels = [], [] - with torch.no_grad(): - for i, (x_s, y_s, *_) in enumerate(loader_te): - x_s, y_s = x_s.to(device), y_s.to(device) - pred, *_ = model_local.infer_y_vpicn(x_s) - list_vec_preds.append(pred) - list_vec_labels.append(y_s) - if i > max_batches: - break - accuracy_y = fun_acc(list_vec_preds, list_vec_labels) - acc_y = accuracy_y.cpu().numpy().item() - return acc_y
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/perf_metrics.html b/docs/build/html/_modules/domainlab/utils/perf_metrics.html deleted file mode 100644 index 5a9de73ce..000000000 --- a/docs/build/html/_modules/domainlab/utils/perf_metrics.html +++ /dev/null @@ -1,398 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.perf_metrics — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.perf_metrics

-"""Classification Performance"""
-import torch
-from torchmetrics.classification import (AUC, AUROC, Accuracy, ConfusionMatrix,
-                                         F1Score, Precision, Recall,
-                                         Specificity)
-
-
-
[docs]class PerfMetricClassif(): - """Classification Performance metrics""" - def __init__(self, num_classes, average='macro'): - super().__init__() - self.acc = Accuracy(num_classes=num_classes, average=average) - self.precision = Precision(num_classes=num_classes, average=average) - self.recall = Recall(num_classes=num_classes, average=average) - self.f1_score = F1Score(num_classes=num_classes, average=average) - self.auroc = AUROC(num_classes=num_classes, average=average) - self.specificity = Specificity(num_classes=num_classes, - average=average) - self.confmat = ConfusionMatrix(num_classes=num_classes) - -
[docs] def cal_metrics(self, model, loader_te, device, max_batches=None): - """ - :param model: - :param loader_te: - :param device: for final test, GPU can be used - :param max_batches: - maximum number of iteration for data loader, used to - probe performance with less computation burden. - default None, which means to traverse the whole dataset - """ - self.acc.reset() - self.precision.reset() - self.recall.reset() - self.f1_score.reset() - self.auroc.reset() - self.specificity.reset() - self.confmat.reset() - self.acc = self.acc.to(device) - self.precision = self.precision.to(device) - self.recall = self.recall.to(device) - self.f1_score = self.f1_score.to(device) - self.auroc = self.auroc.to(device) - self.specificity = self.specificity.to(device) - self.confmat = self.confmat.to(device) - model.eval() - model_local = model.to(device) - if max_batches is None: - max_batches = len(loader_te) - with torch.no_grad(): - for i, (x_s, y_s, *_) in enumerate(loader_te): - x_s, y_s = x_s.to(device), y_s.to(device) - _, prob, _, *_ = model_local.infer_y_vpicn(x_s) - _, target_label = torch.max(y_s, 1) - # self.acc.update(pred_label, target_label) # bug found by xinyuejohn - # pred_label is (N,C) which we need to convert to (N) - # prob is (N,C) which is fine for torchmetrics - self.acc.update(prob, target_label) - self.precision.update(prob, target_label) - self.recall.update(prob, target_label) - self.specificity.update(prob, target_label) - self.f1_score.update(prob, target_label) - self.auroc.update(prob, target_label) - self.confmat.update(prob, target_label) - if i > max_batches: - break - - acc_y = self.acc.compute() - precision_y = self.precision.compute() - recall_y = self.recall.compute() - specificity_y = self.specificity.compute() - f1_score_y = self.f1_score.compute() - auroc_y = self.auroc.compute() - confmat_y = self.confmat.compute() - dict_metric = {"acc": acc_y, - "precision": precision_y, - "recall": recall_y, - "specificity": specificity_y, - "f1": f1_score_y, - "auroc": auroc_y, - "confmat": confmat_y} - keys = list(dict_metric) - keys.remove("confmat") - for key in keys: - dict_metric[key] = dict_metric[key].cpu().numpy().sum() - dict_metric["confmat"] = dict_metric["confmat"].cpu().numpy() - return dict_metric
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/test_img.html b/docs/build/html/_modules/domainlab/utils/test_img.html deleted file mode 100644 index e1b1a9fc2..000000000 --- a/docs/build/html/_modules/domainlab/utils/test_img.html +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.test_img — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.test_img

-import torch
-
-
-
[docs]def mk_img(i_h, i_ch=3, batch_size=5): - img = torch.rand(i_h, i_h) # uniform distribution [0,1] - # x = torch.clamp(x, 0, 1) - img.unsqueeze_(0) - img = img.repeat(i_ch, 1, 1) # RGB image - img.unsqueeze_(0) - img = img.repeat(batch_size, 1, 1, 1) - return img
- -
[docs]def mk_rand_label_onehot(target_dim=10, batch_size=5): - label_scalar = torch.randint(high=target_dim, size=(batch_size, )) - label_scalar2 = label_scalar.unsqueeze(1) - label_zeros = torch.zeros(batch_size, target_dim) - label_onehot = torch.scatter(input=label_zeros, dim=1, index=label_scalar2, value=1.0) - return label_onehot
- -
[docs]def mk_rand_xyd(ims, y_dim, d_dim, batch_size): - imgs = mk_img(i_h=ims, batch_size=batch_size) - ys = mk_rand_label_onehot(target_dim=y_dim, batch_size=batch_size) - ds = mk_rand_label_onehot(target_dim=d_dim, batch_size=batch_size) - return imgs, ys, ds
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/u_import.html b/docs/build/html/_modules/domainlab/utils/u_import.html deleted file mode 100644 index e589ffdb4..000000000 --- a/docs/build/html/_modules/domainlab/utils/u_import.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.u_import — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.u_import

-import os
-from importlib.machinery import SourceFileLoader
-
-
-
[docs]def import_path(path): - path = os.path.expanduser(path) - if path[0] == "/": - full_path = path - else: - dir_path = os.getcwd() - full_path = os.path.join(dir_path, path) - return SourceFileLoader(fullname=full_path, path=full_path).load_module()
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/u_import_net_module.html b/docs/build/html/_modules/domainlab/utils/u_import_net_module.html deleted file mode 100644 index 9f55dd5e8..000000000 --- a/docs/build/html/_modules/domainlab/utils/u_import_net_module.html +++ /dev/null @@ -1,358 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.u_import_net_module — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.u_import_net_module

-"""
-import external neural network implementation
-"""
-
-from domainlab.utils.u_import import import_path
-
-
-
[docs]def build_external_obj_net_module_feat_extract(mpath, dim_y, - remove_last_layer): - """ The user provide a function to initiate an object of the neural network, - which is fine for training but problematic for persistence of the trained - model since it is created externally. - :param mpath: path of external python file where the neural network - architecture is defined - :param dim_y: dimension of features - """ - # other possibility - # na_external_module = "name_external_module" # the dummy module name - # spec = importlib.util.spec_from_file_location( - # name=na_external_module, - # location=path_net_feat_extract) - # module_external = importlib.util.module_from_spec(spec) - # sys.modules[na_external_module] = module_external - # register the name of the external module - # spec.loader.exec_module(module_external) - - net_module = import_path(mpath) - name_signature = "build_feat_extract_net(dim_y, \ - remove_last_layer)" - # @FIXME: hard coded, move to top level __init__ definition in domainlab - name_fun = name_signature[:name_signature.index("(")] - if hasattr(net_module, name_fun): - try: - net = getattr(net_module, name_fun)(dim_y, remove_last_layer) - except Exception: - print("function %s should return a neural network (pytorch module) that \ - that extract features from an image" % (name_signature)) - raise - if net is None: - raise RuntimeError("the pytorch module returned by %s is None" - % (name_signature)) - else: - raise RuntimeError("Please implement a function %s \ - in your external python file" - % (name_signature)) - return net
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/utils_class.html b/docs/build/html/_modules/domainlab/utils/utils_class.html deleted file mode 100644 index a356750bc..000000000 --- a/docs/build/html/_modules/domainlab/utils/utils_class.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.utils_class — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.utils_class

-import functools
-import inspect
-
-
-
[docs]def store_args(method): - """Stores provided method args as instance attributes. - """ - argspec = inspect.getfullargspec(method) - defaults = {} - if argspec.defaults is not None: - defaults = dict( - zip(argspec.args[-len(argspec.defaults):], argspec.defaults)) - if argspec.kwonlydefaults is not None: - defaults.update(argspec.kwonlydefaults) - arg_names = argspec.args[1:] - - @functools.wraps(method) - def wrapper(*positional_args, **keyword_args): - self = positional_args[0] - # Get default arg values - args = defaults.copy() - # Add provided arg values - for name, value in zip(arg_names, positional_args[1:]): - args[name] = value - args.update(keyword_args) - self.__dict__.update(args) - return method(*positional_args, **keyword_args) - - return wrapper
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/utils_classif.html b/docs/build/html/_modules/domainlab/utils/utils_classif.html deleted file mode 100644 index 651c539af..000000000 --- a/docs/build/html/_modules/domainlab/utils/utils_classif.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.utils_classif — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.utils_classif

-import numpy as np
-import torch
-from torch.nn import functional as F
-
-
-
[docs]def mk_dummy_label_list_str(prefix, dim): - """ - only used for testing, to generate list of class/domain label names - """ - return [prefix + str(i) for i in range(dim)]
- - -
[docs]def logit2preds_vpic(logit): - """ - :logit: batch of logit vector - :return: vector of one-hot, - vector of probability, - index, - maximum probability - """ - mat_prob = F.softmax(logit, dim=1) - # get the index of the maximum softmax probability - max_prob, max_ind = torch.topk(mat_prob, 1) - # convert the digit(s) to one-hot tensor(s) - one_hot = logit.new_zeros(mat_prob.size()) - one_hot = one_hot.scatter_(dim=1, index=max_ind, value=1.0) - return one_hot, mat_prob, max_ind, max_prob
- -
[docs]def get_label_na(tensor_ind, list_str_na): - """ - given list of label names in strings, map tensor of index to label names - """ - arr_ind_np = tensor_ind.cpu().numpy() - arr_ind = np.squeeze(arr_ind_np, axis=1) # explicitly use axis=1 to deal with edge case of only - # instance left - # list_ind = list(arr_ind): if there is only dimension 1 tensor_ind, then there is a problem - list_ind = arr_ind.tolist() - list_na = [list_str_na[ind] for ind in list_ind] - return list_na
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/utils_cuda.html b/docs/build/html/_modules/domainlab/utils/utils_cuda.html deleted file mode 100644 index 67f389e46..000000000 --- a/docs/build/html/_modules/domainlab/utils/utils_cuda.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.utils_cuda — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.utils_cuda

-import torch
-
-
-
[docs]def get_device(flag_no_cu): - flag_cuda = torch.cuda.is_available() and (not flag_no_cu) - device = torch.device("cuda" if flag_cuda else "cpu") - print("") - print("using device:", str(device)) - print("") - return device
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/domainlab/utils/utils_img_sav.html b/docs/build/html/_modules/domainlab/utils/utils_img_sav.html deleted file mode 100644 index ee3067c36..000000000 --- a/docs/build/html/_modules/domainlab/utils/utils_img_sav.html +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils.utils_img_sav — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Source code for domainlab.utils.utils_img_sav

-import os
-from pathlib import Path
-
-import matplotlib.pyplot as plt
-from torchvision.utils import make_grid, save_image
-
-
-
[docs]def mk_fun_sav_img(path=".", nrow=8, folder_na=""): - """ - create torchvision.utils image saver - """ - Path(path).mkdir(parents=True, exist_ok=True) - - def my_sav_img(comparison_tensor_stack, name, title=None): - f_p = os.path.join(path, folder_na, name) - Path(os.path.dirname(f_p)).mkdir(parents=True, exist_ok=True) - print("saving to ", f_p) - # works also if tensor is already in cpu - tensor = comparison_tensor_stack.cpu() - if title is None: - save_image(tensor=tensor, nrow=nrow, fp=f_p) - else: - img_grid = make_grid(tensor=tensor, nrow=nrow) - sav_add_title(img_grid, path=f_p, title="hi") - return my_sav_img
- - -
[docs]def sav_add_title(grid_img, path, title): - """ - add title and save image as matplotlib.pyplot - """ - fig = plt.gcf() # get current figure - plt.imshow(grid_img.permute(1, 2, 0)) - plt.title(title) - fig.savefig(path) - fig.clf() # clear figure
-
- -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html deleted file mode 100644 index 9e9678e5c..000000000 --- a/docs/build/html/_modules/index.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Overview: module code — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

All modules for which code is available

- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/_sources/docHDUVA.md.txt b/docs/build/html/_sources/docHDUVA.md.txt deleted file mode 100644 index edb680595..000000000 --- a/docs/build/html/_sources/docHDUVA.md.txt +++ /dev/null @@ -1,65 +0,0 @@ -# HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION - -HDUVA builds on a generative approach within the framework of variational autoencoders to facilitate generalization to new domains without supervision. HDUVA learns representations that disentangle domain-specific information from class-label specific information even in complex settings where domain structure is not observed during training. - -## Model Overview -More specifically, HDUVA is based on three latent variables that are used to model distinct sources of variation and are denoted as $z_y$, $z_d$ and $z_x$. $z_y$ represents class specific information, $z_d$ represents domain specific information and $z_x$ models residual variance of the input. We introduce an additional hierarchical level and use a continuous latent representation s to model (potentially unobserved) domain structure. This means that we can encourage disentanglement of the latent variables through conditional priors without the need of conditioning on a one-hot-encoded, observed domain label. The model along with its parameters and hyperparameters is shown in Figure 1: - -
- PGM for HDUVA -
Figure 1: Probabilistic graphical model for HDUVA:Hierarchical Domain Unsupervised Variational Autoencoding.
-
- - - -Note that as part of the model a latent representation of $X$ is concatentated with $s$ and $z_d$ (dashed arrows), requiring respecive encoder networks. - -## Evidence lower bound and overall loss -The ELBO of the model can be decomposed into 4 different terms: - -Likelihood: $E_{q(z_d, s|x), q(z_x|x), q(z_y|x)}\log p_{\theta}(x|s, z_d, z_x, z_y)$ - -KL divergence weighted as in the Beta-VAE: $-\beta_x KL(q_{\phi_x}(z_x|x)||p_{\theta_x}(z_x)) - \beta_y KL(q_{\phi_y}(z_y|x)||p_{\theta_y}(z_y|y))$ - -Hierarchical KL loss (domain term): $- \beta_d E_{q_{\phi_s}(s|x), q_{\phi_d}(z_d|x, s)} \log \frac{q_{\phi_d}(z_d|x, s)}{p_{\theta_d}(z_d|s)}$ - -Hierarchical KL loss (topic term): $-\beta_t E_{q_{\phi_s}(s|x)}KL(q_{\phi_s}(s|x)||p_{\theta_s}(s|\alpha))$ - -In addition, we construct the overall loss by adding an auxiliary classsifier, by adding an additional term to the ELBO loss, weighted with $\gamma_y$: - - -## Hyperparameters loss function -For fitting the model, we need to specify the 4 $\beta$-weights related to the the different terms of the ELBO ( $\beta_x$ , $\beta_y$, $\beta_d$, $\beta_t$) as well as $\gamma_y$. - -## Model parameters -In addition to these hyperparameters, the following model parameters can be specified: - -- Size of latent space for domain-specific information: zd_dim -- Size of latent space for residual variance: zx_dim -- Size of latent space for class-specific information: zy_dim -- Size of latent space for topics $s$: topic_dim -- Size of latent space for latent image representation for topic: topic_h_dim -- Size of latent space for latent image representation for domain: img_h_dim - -Finally, 2 models need to be specified: A network converting an image to a topic distribution (of size topic_h_dim) and an encoder converting an image to a latent representation that can be concatenated to $z_d$ (size img_h_dim). The names and paths of the networks are: - -- nname_topic_distrib_img2topic -- npath_topic_distrib_img2topic - -and -- nname_encoder_sandwich_layer_img2h4zd -- npath_encoder_sandwich_layer_img2h4zd - - -## Hyperparameter warmup -Finally, the number of epochs for hyper-parameter warm-up can be specified via the argument warmup - -Please cite our paper if you find it useful! -```text -@inproceedings{sun2021hierarchical, - title={Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization}, - author={Sun, Xudong and Buettner, Florian}, - booktitle={ICLR 2021 RobustML workshop, https://arxiv.org/pdf/2101.09436.pdf}, - year={2021} -} -``` diff --git a/docs/build/html/_sources/docJiGen.md.txt b/docs/build/html/_sources/docJiGen.md.txt deleted file mode 100644 index a26331b04..000000000 --- a/docs/build/html/_sources/docJiGen.md.txt +++ /dev/null @@ -1,14 +0,0 @@ -# JiGen - -The JiGen method proposed in [https://arxiv.org/abs/2007.01434](https://arxiv.org/abs/1903.06864) by Carlucci et al. extends the understanding of the concept of spatial correlation in the neuronal network by training the network not only on a classification task, but also on solving jigsaw puzzles. - -For the jigsaw puzzles the images are split into $n \times n$ patches and permutated. - -The model is to predict the permutation index which result in the permutated image. - -To be able to solve the classification problem and the jigsaw puzzle in parallel, shuffled and ordered images will first be fed into a convolutional network for feature extraction and will then be given to the image classifier and the jigsaw classifier. - -For the training of classificaiton task the network uses a cross-entropy loss for both tasks while weighting the jigsaw classifier by a hyper parameter. Additionally the relative ratio or probability of shuffling the tiles of one instance from training data set is given by another hyper parameter. - -The advantage of this method is that is does not require domain label, as the jigsaw puzzle can be solved despite the missing domain labels. - diff --git a/docs/build/html/_sources/doc_algos.md.txt b/docs/build/html/_sources/doc_algos.md.txt deleted file mode 100644 index 664f40bfc..000000000 --- a/docs/build/html/_sources/doc_algos.md.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Overview of implemented models and algorithms - -Note DomainLab decomposes the concept of model from network and algorithm. That is, the model only defines the loss of the neural network, while the architecture of the neural network can be specified independently as a component of the model, and algorithm is model with a specified trainer and observer. Algorithm share the same name as model with a default trainer specified. - -## algorithm "deepall" -Pool all domains together and train an ERM (empirical risk minimization) model - -## algorithm "matchdg" -Mahajan, Divyat, Shruti Tople, and Amit Sharma. "Domain generalization using causal matching." International Conference on Machine Learning. PMLR, 2021. -## algorithm "diva" -Ilse, Maximilian, et al. "Diva: Domain invariant variational autoencoders." Medical Imaging with Deep Learning. PMLR, 2020. - -## algorithm "hduva" -Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization: https://arxiv.org/pdf/2101.09436.pdf, ICLR 2020 RobustML. - -## algorithm "dann": -Ganin, Yaroslav, et al. "Domain-adversarial training of neural networks." The journal of machine learning research 17.1 (2016): 2096-2030. - -## algorithm "jigen": -Carlucci, Fabio M., et al. "Domain generalization by solving jigsaw puzzles." Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019. https://arxiv.org/abs/1903.06864 - -## algorithm deepall, dann, diva with trainer "dial" -Levi, Matan, Idan Attias, and Aryeh Kontorovich. "Domain invariant adversarial learning.", Transactions on Machine Learning Research, arXiv preprint arXiv:2104.00322 (2021). diff --git a/docs/build/html/_sources/doc_benchmark.md.txt b/docs/build/html/_sources/doc_benchmark.md.txt deleted file mode 100644 index 7006ca05f..000000000 --- a/docs/build/html/_sources/doc_benchmark.md.txt +++ /dev/null @@ -1,55 +0,0 @@ -# Benchmarking with DomainLab - -The package offers the ability to benchmark different algorithms against each other. -The results are collected in a csv file, but also prepared in charts. - -Within each benchmark, two aspects are considered: -1. Stochastic variation: Variation of the performance with respect to different random seeds. -2. Sensitivity to selected hyperparameters: By sampling hyperparameters randomly, -the performance with respect to different hyperparameter choices is investigated. - -## Setting up a benchmark -The benchmark is configured in a yaml file. We refer to the -[demo_benchmark.yaml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_benchmark.yaml) -for a documented example. As one can see here, the user has to select: -- Common arguments for all tasks. This typically includes the dataset on which the benchmark -shall be performed, as well as the number of epochs and batch size for training. -Here also the number of different random seeds and hyperparameter samples is set. -- The domains which are used as leave-one-out for testing. -- Different tasks, where each task contains: (1) Fixed parameters specific for this task, -typically the algorithm name and related arguments and (2) varying hyperparameters, for which -the sensitivity shall be investigated. - -Set `sampling_seed` for a fully reproducible benchmark. - -## Configure hyperparameter sampling -An example files of the possibilities for hyperparameter sampling is -[demo_hypeparameter_sampling.yml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_hyperparameter_sampling.yml). -This file is of course an extract of [demo_benchmark.yaml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_benchmark.yaml), -the sampling for benchmarks is specified directly in this single configuration file. - -In this example we can see: -- Every node containing `aname` is considered as a task -- Hyperparameters can be sampled from different distributions and -- Constraints between the hyperparameters of the same task can be specified. -- By using the `categorical` distribution type, a list of valid values for a hyperparameter can be specified. -- Equality constraints are not supported in the constraints section. To -enforce equality of two hyperparameters use the `reference` key, see `p4` of `Task1`. -References are supported only to sampled hyperparameters, referencing a reference -results in undefined behaviour. - -Note that for sampling, there is always first a sample drawn ignoring the constraints, which -is then possibly rejected by the constraints. If 10,000 samples are rejected in a row, the sampling -aborts with error. - -## Running a benchmark -For executing the benchmark, a sample command can be found -[here](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/benchmark/run_snakemake.sh). -If several cores are provided, the benchmark is parallelized per hyperparameter sample and -task. - -## Obtained results -All files created by this benchmark are saved in the given output directory. -The sampled hyperparameters can be found in `hyperparameters.csv`. -The performance of the different runs can be found in `results.csv`. Moreover, there is -the `graphics` subdirectory, in which the values from `results.csv` are visualized for interpretation. diff --git a/docs/build/html/_sources/doc_custom_nn.md.txt b/docs/build/html/_sources/doc_custom_nn.md.txt deleted file mode 100644 index 7126884ba..000000000 --- a/docs/build/html/_sources/doc_custom_nn.md.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Custom Neural Network - -To use a custom neural network, the user has to implement the following signature in a python file and feed into this library via `--npath`. - - -``` -def build_feat_extract_net(dim_y, remove_last_layer): -``` - -See examples below from `--npath=examples/nets/resnet.py` where the examples can be found in the examples folder of the code repository. - -## Custom Neural Network Examples - - - -### algorithm 'deepall' with custom neural network - -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py -``` - -### algorithm 'matchdg' with custom neural network - -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py -``` diff --git a/docs/build/html/_sources/doc_diva.md.txt b/docs/build/html/_sources/doc_diva.md.txt deleted file mode 100644 index 14ddcaa38..000000000 --- a/docs/build/html/_sources/doc_diva.md.txt +++ /dev/null @@ -1,39 +0,0 @@ -# DIVA: Domain Invariant Variational Autoencoders - -DIVA approaches the domain generalization problem with a variational autoencoder -with three latent variables, using three independent encoders. - -By encouraging the network to store the domain, -class and residual features in one of the latent space respectively the class specific information -shall be disentangled. - -In order to obtain marginally independent latent variables, the density of the domain -and class latent space is conditioned on the domain and class respectively. These densities are parameterized -by learnable parameters. During training, all three latent variables are then fed into a single decoder -reconstructing the image. - -Additionally, two classifiers are trained, predicting the domain and class label -from the respective latent variable, emphasizing to capture these information in this variables. -This leads to an overall large network. However, during inference only the class encoder and classifier -is used. The experiments are showing that it is indeed possible to disentangle the information in their -test setting. - -Also in a semi-supervised setting, where class labels are missing for some data or domains, -the classification accuracy can be further improved. This is an advantage in the sense that prediction -accuracy turns out to be notably better if the training contained a domain close to the test domain. -Therefore, this semi-supervised setup allows to prepare for new domains by some additional training -needing only samples of the new domain, but no class labels. In the end however, DIVA always needs domain -labels and does not support a fully unsupervised setting. Since it is not always clear what different domains -actually exist, this can lead to problems and decreased performance. - -**Model parameters:** -the following model parameters can be specified: - -- Size of latent space for domain-specific information: zd_dim -- Size of latent space for residual variance: zx_dim -- Size of latent space for class-specific information: zy_dim -- Multiplier for y classifier ($\alpha_y$ of eq. (2) in paper below): gamma_y -- Multiplier for d classifier ($\alpha_d$ of eq. (2) in paper below): gamma_d - -_Reference:_ -DIVA: Domain Invariant Variational Autoencoders, https://arxiv.org/pdf/1905.10427.pdf, Medical Imaging with Deep Learning. PMLR, 2020. diff --git a/docs/build/html/_sources/doc_examples.md.txt b/docs/build/html/_sources/doc_examples.md.txt deleted file mode 100644 index e48424822..000000000 --- a/docs/build/html/_sources/doc_examples.md.txt +++ /dev/null @@ -1,143 +0,0 @@ -# Examples - -## Colored version of MNIST - -### leave one domain out -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 -``` - -### choose train and test -``` -python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5 -``` - -### make a sanity check for the dataset using 8 instances from each domain and from each class -``` -python main_out.py --te_d=0 --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 --san_check --san_num=4 -``` - -### generation of images -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 --gen -``` - -### use hduva on color mnist, train on 2 domains -``` -python main_out.py --tr_d 0 1 2 --te_d 3 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - -### hduva is domain-unsupervised, so it works also with a single domain -``` -python main_out.py --tr_d 0 --te_d 3 4 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - - -## Larger images: - -### model diva with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -### model diva with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --npath=examples/nets/resnet.py --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -### model deepall with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --nname=alexnet -``` - -### model dann with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=dann --nname=alexnet -``` - -### model jigen with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=jigen --nname=alexnet --pperm=1 --nperm=100 --grid_len=3 -``` - -### model matchdg with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --nname=alexnet -``` - -### hduva with implemented neural network -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - -### hduva use alex net -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=alexnet -``` - - -## Custom Neural Network - -### model deepall with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py -``` - -### model matchdg with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py -``` - -### hduva use custom net for sandwich encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --npath_encoder_sandwich_layer_img2h4zd=examples/nets/resnet.py -``` - -### hduva use custom net for topic encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --npath_topic_distrib_img2topic=examples/nets/resnet.py --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - -### hduva use custom net for classification encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --npath=examples/nets/resnet.py --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - - -## User defined tasks - -### Folder Task -#### Folder Task with implemented neural network -``` -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 -``` - -#### Folder Task with externally user defined neural network -``` -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -### ImagePath Task -#### ImagePath Task with implemented algorithm -``` -python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 -``` - -#### ImagePath Task with externally user defined neural network -``` -python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -## Custom algorithm defined in external python file -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet -``` - -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py -``` - -## Adversarial images training -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=deepall_dial --nname=conv_bn_pool_2 -``` diff --git a/docs/build/html/_sources/doc_extend_contribute.md.txt b/docs/build/html/_sources/doc_extend_contribute.md.txt deleted file mode 100644 index 245ca50b3..000000000 --- a/docs/build/html/_sources/doc_extend_contribute.md.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Extend or contribute with a custom domain generalization algorithm - -## External extension by implementing your custom models - -Look at this example - -``` -cd .. -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet - -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py -``` - -where the example python file corresponding to `--apath` defines a model which contains several modules that can be customized to different neural networks via `--npath_argna2val` if the neural network is specified in a python file -or `nname_argna2val` if the neural network is already implemented. - -## Internal extension for more advanced contribution -- implement `domainlab/algos/builder_your-algorithm-name.py` -- add your algorithm into `domainlab/algos/zoo_algos.py` by adding `chain = NodeAlgoBuilder[your-algorithm-name](chain)` -- note that all algorithms will be converted to lower case! -- make a pull request - - -### Design -![Design Diagram](libDG.svg) diff --git a/docs/build/html/_sources/doc_output.md.txt b/docs/build/html/_sources/doc_output.md.txt deleted file mode 100644 index 61c67e17a..000000000 --- a/docs/build/html/_sources/doc_output.md.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Output structure - -By default, this package generates outputs into a folder `zoutput` relative to the current working directory, which the user can alter by specifying the corresponding command line argument. - -The output structure is something similar to below. ([] means the folder might or might not exist, texts inside () are comments) - -``` -zoutput/ -├── aggrsts (aggregation of results) -│ ├── task1_test_domain1_tagName.csv -│ ├── task2_test_domain3_tagName.csv -│ -│ -├── [gen] (counterfactual image generation, only exist for generative models with "--gen" specified) -│ ├── [task1_test_domain1] -│ -└── saved_models (persisted pytorch model) - ├── task1_algo1_git-commit-hashtag1_seed_1_instance_wise_predictions.txt (instance wise prediction of the model) - ├── [task1_algo1_git-commit-hashtag1_seed_1.model] (only exist if with command line argument "--keep_model") - ... -``` - -`aggrst` folder is aggregating results from several runs corresponding to the same train test split of the identical task, that means after each run, an extra line will be appended to the file corresponding to the same train test split of the identical task, so that it is convenient to compare between different algorithms and configurations upon the same train test split of the identical task. - -`saved_models` folder contains instance wise prediction in a text file for each run, and potentially the persisted model on the hard disk (by default, these models will be deleted after run is completed). diff --git a/docs/build/html/_sources/doc_tasks.md.txt b/docs/build/html/_sources/doc_tasks.md.txt deleted file mode 100644 index fcbf7110d..000000000 --- a/docs/build/html/_sources/doc_tasks.md.txt +++ /dev/null @@ -1,136 +0,0 @@ -# Task Specification - -The package offers various ways to specify the domain generalization task according to user's need. - -## TaskPathList -The user need to provide a python file indicating the root directories where images (data) from each domain are located, and for each domain, the user shall provide a plain text file indicating the file names. - -An example python file can be found in the [examples directory of the repository](https://github.com/marrlab/DomainLab/blob/master/examples/tasks/demo_task_path_list_small.py) with the corresponding data be found at [the data directory of the repository](https://github.com/marrlab/DomainLab/tree/master/data), where the text file indicating which file correspond to which class label (starting from 1) can be found at [example text file](https://github.com/marrlab/DomainLab/blob/master/data/pacs_split/art_painting_10.txt). -The user should specify the location of the python file via command line arguments `--tpath` - -## TaskFolder -In this mode, we assume there are structured folders where each folder contains all data from one domain, and each domain folder contains subfolders corresponding to different classes. See examples below. - -### Data organization -To give an example, suppose we have a classification task to classify between car, dog, human, chair and bird and there are 3 data sources (domains) with folder name "folder_a", "folder_b" and "folder_c" respectively as shown below. - -In each folder, the images are organized in sub-folders by their class. For example, "/path/to/3rd_domain/folder_c/dog" folder contains all the images of class "dog" from the 3rd domain. - -It might be the case that across the different data sources the same class is named differently. For example, in the 1st data source, the class dog is stored in sub-folder named -"hund", in the 2nd data source, the dog is stored in sub-folder named "husky" and in the 3rd data source, the dog is stored in sub-folder named "dog". - -It might also be the case that some classes exist in one data source but does not exist in another data source. For example, folder "/path/to/2nd_domain/folder_b" does not have a sub-folder for class "human". - -Folder structure of the 1st domain: -``` - ── /path/to/1st_domain/folder_a - ├── auto - ├── hund - ├── mensch - ├── stuhl - └── vogel - -``` -Folder structure of the 2nd domain: - -``` - ── /path/to/2nd_domain/folder_b - ├── bird - ├── drive - ├── sit - └── husky -``` -Folder structure of the 3rd domain: - -``` - ── /path/to/3rd_domain/folder_c - ├── dog - ├── flying - ├── sapiens - ├── sofa - └── vehicle -``` - -### Specify the task with domainlab API -The user is expected to implement something similar to the following code in a separate python file with a function with signature `get_task(na=None)`. -``` -import os -from torchvision import transforms - -from domainlab.tasks import mk_task_folder, ImSize - -# specify torchvision transformations for training -trans_tr = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.RandomResizedCrop(224, scale=(0.7, 1.0)), - transforms.RandomHorizontalFlip(), - transforms.ColorJitter(0.3, 0.3, 0.3, 0.3), - transforms.RandomGrayscale(), - transforms.ToTensor(), - transforms.Normalize([0.485, 0.456, 0.406], - [0.229, 0.224, 0.225]) -]) - -# specify torchvision transformations at test/inference time -trans_te = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.ToTensor(), - transforms.Normalize([0.485, 0.456, 0.406], - [0.229, 0.224, 0.225]) -]) - - -chain = mk_task_folder(extensions={"domain1": "jpg", "domain2": "jpg", "domain3": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "domain1": {"auto": "car", "stuhl": "chair"}, - "domain2": {"vehicle": "car", "sofa": "chair"}, - "domain3": {"drive": "car", "sit": "chair"} - }, - dict_domain_img_trans={ - "domain1": trans_tr, - "domain2": trans_tr, - "domain3": trans_tr, - }, - img_trans_te=trans_te, - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "domain1": os.path.join("/path/to/1st_domain", "folder_a"), - "domain2": os.path.join("/path/to/2nd_domain", "folder_b"), - "domain3": os.path.join("/path/to/3rd_domain", "folder_c")}, - taskna="task_demo") - -def get_task(na=None): # the package will call this function to get the task - return chain -``` -The domainlab function to create task in this example is `domainlab.tasks.mk_task_folder` -``` -from domainlab.tasks import mk_task_folder -print(mk_task_folder.__doc__) - -extensions: a python dictionary with key as the domain name -and value as the file extensions of the image. - -list_str_y: a python list with user defined class names where -the order of the list matters. - -dict_domain_folder_name2class: a python dictionary, with key -as the user specified domain name, value as a dictionary to map the -sub-folder name of each domain's class folder into the user defined -common class name. - -dict_domain_img_trans: a python dictionary with keys as the user -specified domain name, value as a user defined torchvision transform. -This feature allows carrying out different transformation (composition) to different -domains at training time. - -img_trans_te: at test or inference time, we do not have knowledge -of domain information so only a unique transform (composition) is allowed. - -isize: domainlab.tasks.ImSize(image channel, image height, image width) - -dict_domain2imgroot: a python dictionary with keys as user specified domain names and values -as the absolute path to each domain's data. - -taskna: user defined task name -``` diff --git a/docs/build/html/_sources/domainlab.algos.compos.rst.txt b/docs/build/html/_sources/domainlab.algos.compos.rst.txt deleted file mode 100644 index 991f8693e..000000000 --- a/docs/build/html/_sources/domainlab.algos.compos.rst.txt +++ /dev/null @@ -1,53 +0,0 @@ -domainlab.algos.compos package -============================== - -Submodules ----------- - -domainlab.algos.compos.matchdg\_args module -------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_args - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_base module -------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_base - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_ctr\_erm module ------------------------------------------------ - -.. automodule:: domainlab.algos.compos.matchdg_ctr_erm - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_match module --------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_match - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_utils module --------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_utils - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos.compos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.algos.msels.rst.txt b/docs/build/html/_sources/domainlab.algos.msels.rst.txt deleted file mode 100644 index 473a0663e..000000000 --- a/docs/build/html/_sources/domainlab.algos.msels.rst.txt +++ /dev/null @@ -1,37 +0,0 @@ -domainlab.algos.msels package -============================= - -Submodules ----------- - -domainlab.algos.msels.a\_model\_sel module ------------------------------------------- - -.. automodule:: domainlab.algos.msels.a_model_sel - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.msels.c\_msel module ------------------------------------- - -.. automodule:: domainlab.algos.msels.c_msel - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.msels.c\_msel\_oracle module --------------------------------------------- - -.. automodule:: domainlab.algos.msels.c_msel_oracle - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos.msels - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.algos.observers.rst.txt b/docs/build/html/_sources/domainlab.algos.observers.rst.txt deleted file mode 100644 index 1ecb7c2d9..000000000 --- a/docs/build/html/_sources/domainlab.algos.observers.rst.txt +++ /dev/null @@ -1,45 +0,0 @@ -domainlab.algos.observers package -================================= - -Submodules ----------- - -domainlab.algos.observers.a\_observer module --------------------------------------------- - -.. automodule:: domainlab.algos.observers.a_observer - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.observers.b\_obvisitor module ---------------------------------------------- - -.. automodule:: domainlab.algos.observers.b_obvisitor - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.observers.c\_obvisitor\_cleanup module ------------------------------------------------------- - -.. automodule:: domainlab.algos.observers.c_obvisitor_cleanup - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.observers.c\_obvisitor\_gen module --------------------------------------------------- - -.. automodule:: domainlab.algos.observers.c_obvisitor_gen - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos.observers - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.algos.rst.txt b/docs/build/html/_sources/domainlab.algos.rst.txt deleted file mode 100644 index 9733ba09a..000000000 --- a/docs/build/html/_sources/domainlab.algos.rst.txt +++ /dev/null @@ -1,104 +0,0 @@ -domainlab.algos package -======================= - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - domainlab.algos.compos - domainlab.algos.msels - domainlab.algos.observers - domainlab.algos.trainers - -Submodules ----------- - -domainlab.algos.a\_algo\_builder module ---------------------------------------- - -.. automodule:: domainlab.algos.a_algo_builder - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_custom module --------------------------------------- - -.. automodule:: domainlab.algos.builder_custom - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_dann module ------------------------------------- - -.. automodule:: domainlab.algos.builder_dann - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_deepall module ---------------------------------------- - -.. automodule:: domainlab.algos.builder_deepall - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_dial module ------------------------------------- - -.. automodule:: domainlab.algos.builder_dial - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_diva module ------------------------------------- - -.. automodule:: domainlab.algos.builder_diva - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_hduva module -------------------------------------- - -.. automodule:: domainlab.algos.builder_hduva - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_jigen1 module --------------------------------------- - -.. automodule:: domainlab.algos.builder_jigen1 - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_matchdg module ---------------------------------------- - -.. automodule:: domainlab.algos.builder_matchdg - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.zoo\_algos module ---------------------------------- - -.. automodule:: domainlab.algos.zoo_algos - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.algos.trainers.rst.txt b/docs/build/html/_sources/domainlab.algos.trainers.rst.txt deleted file mode 100644 index 3ac371ef2..000000000 --- a/docs/build/html/_sources/domainlab.algos.trainers.rst.txt +++ /dev/null @@ -1,61 +0,0 @@ -domainlab.algos.trainers package -================================ - -Submodules ----------- - -domainlab.algos.trainers.a\_trainer module ------------------------------------------- - -.. automodule:: domainlab.algos.trainers.a_trainer - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.args\_dial module ------------------------------------------- - -.. automodule:: domainlab.algos.trainers.args_dial - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_basic module --------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_basic - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_dial module -------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_dial - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_matchdg module ----------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_matchdg - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_visitor module ----------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_visitor - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos.trainers - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.compos.nn_zoo.rst.txt b/docs/build/html/_sources/domainlab.compos.nn_zoo.rst.txt deleted file mode 100644 index c75d6059d..000000000 --- a/docs/build/html/_sources/domainlab.compos.nn_zoo.rst.txt +++ /dev/null @@ -1,69 +0,0 @@ -domainlab.compos.nn\_zoo package -================================ - -Submodules ----------- - -domainlab.compos.nn\_zoo.net\_adversarial module ------------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_adversarial - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.net\_classif module --------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.net\_conv\_conv\_bn\_pool\_2 module ------------------------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.net\_gated module ------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_gated - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.nn module ----------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.nn - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.nn\_alex module ----------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.nn_alex - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.nn\_torchvision module ------------------------------------------------ - -.. automodule:: domainlab.compos.nn_zoo.nn_torchvision - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.compos.nn_zoo - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.compos.rst.txt b/docs/build/html/_sources/domainlab.compos.rst.txt deleted file mode 100644 index 7dce11821..000000000 --- a/docs/build/html/_sources/domainlab.compos.rst.txt +++ /dev/null @@ -1,69 +0,0 @@ -domainlab.compos package -======================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - domainlab.compos.nn_zoo - -Submodules ----------- - -domainlab.compos.a\_nn\_builder module --------------------------------------- - -.. automodule:: domainlab.compos.a_nn_builder - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.builder\_nn\_alex module ------------------------------------------ - -.. automodule:: domainlab.compos.builder_nn_alex - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.builder\_nn\_conv\_bn\_relu\_2 module ------------------------------------------------------- - -.. automodule:: domainlab.compos.builder_nn_conv_bn_relu_2 - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.builder\_nn\_external\_from\_file module ---------------------------------------------------------- - -.. automodule:: domainlab.compos.builder_nn_external_from_file - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.utils\_conv\_get\_flat\_dim module ---------------------------------------------------- - -.. automodule:: domainlab.compos.utils_conv_get_flat_dim - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.zoo\_nn module -------------------------------- - -.. automodule:: domainlab.compos.zoo_nn - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.compos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.dsets.rst.txt b/docs/build/html/_sources/domainlab.dsets.rst.txt deleted file mode 100644 index 9de944f19..000000000 --- a/docs/build/html/_sources/domainlab.dsets.rst.txt +++ /dev/null @@ -1,77 +0,0 @@ -domainlab.dsets package -======================= - -Submodules ----------- - -domainlab.dsets.a\_dset\_mnist\_color\_rgb\_solo module -------------------------------------------------------- - -.. automodule:: domainlab.dsets.a_dset_mnist_color_rgb_solo - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_img\_path\_list module --------------------------------------------- - -.. automodule:: domainlab.dsets.dset_img_path_list - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_mnist\_color\_solo\_default module --------------------------------------------------------- - -.. automodule:: domainlab.dsets.dset_mnist_color_solo_default - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_poly\_domains\_mnist\_color\_default module ------------------------------------------------------------------ - -.. automodule:: domainlab.dsets.dset_poly_domains_mnist_color_default - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_subfolder module --------------------------------------- - -.. automodule:: domainlab.dsets.dset_subfolder - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.utils\_color\_palette module --------------------------------------------- - -.. automodule:: domainlab.dsets.utils_color_palette - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.utils\_data module ----------------------------------- - -.. automodule:: domainlab.dsets.utils_data - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.utils\_wrapdset\_patches module ------------------------------------------------ - -.. automodule:: domainlab.dsets.utils_wrapdset_patches - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.dsets - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.exp_protocol.rst.txt b/docs/build/html/_sources/domainlab.exp_protocol.rst.txt deleted file mode 100644 index 752bc744d..000000000 --- a/docs/build/html/_sources/domainlab.exp_protocol.rst.txt +++ /dev/null @@ -1,21 +0,0 @@ -domainlab.exp\_protocol package -=============================== - -Submodules ----------- - -domainlab.exp\_protocol.run\_experiment module ----------------------------------------------- - -.. automodule:: domainlab.exp_protocol.run_experiment - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.exp_protocol - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.models.rst.txt b/docs/build/html/_sources/domainlab.models.rst.txt deleted file mode 100644 index 235c9b0cc..000000000 --- a/docs/build/html/_sources/domainlab.models.rst.txt +++ /dev/null @@ -1,109 +0,0 @@ -domainlab.models package -======================== - -Submodules ----------- - -domainlab.models.a\_model module --------------------------------- - -.. automodule:: domainlab.models.a_model - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.a\_model\_classif module ------------------------------------------ - -.. automodule:: domainlab.models.a_model_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.args\_jigen module ------------------------------------ - -.. automodule:: domainlab.models.args_jigen - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.args\_vae module ---------------------------------- - -.. automodule:: domainlab.models.args_vae - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_custom module -------------------------------------- - -.. automodule:: domainlab.models.model_custom - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_dann module ------------------------------------ - -.. automodule:: domainlab.models.model_dann - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_deep\_all module ----------------------------------------- - -.. automodule:: domainlab.models.model_deep_all - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_diva module ------------------------------------ - -.. automodule:: domainlab.models.model_diva - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_hduva module ------------------------------------- - -.. automodule:: domainlab.models.model_hduva - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_jigen module ------------------------------------- - -.. automodule:: domainlab.models.model_jigen - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_vae\_xyd\_classif module ------------------------------------------------- - -.. automodule:: domainlab.models.model_vae_xyd_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.wrapper\_matchdg module ----------------------------------------- - -.. automodule:: domainlab.models.wrapper_matchdg - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.models - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.rst.txt b/docs/build/html/_sources/domainlab.rst.txt deleted file mode 100644 index b2a98deda..000000000 --- a/docs/build/html/_sources/domainlab.rst.txt +++ /dev/null @@ -1,35 +0,0 @@ -domainlab package -================= - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - domainlab.algos - domainlab.compos - domainlab.dsets - domainlab.exp_protocol - domainlab.models - domainlab.tasks - domainlab.utils - -Submodules ----------- - -domainlab.arg\_parser module ----------------------------- - -.. automodule:: domainlab.arg_parser - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.tasks.rst.txt b/docs/build/html/_sources/domainlab.tasks.rst.txt deleted file mode 100644 index a29b6f973..000000000 --- a/docs/build/html/_sources/domainlab.tasks.rst.txt +++ /dev/null @@ -1,93 +0,0 @@ -domainlab.tasks package -======================= - -Submodules ----------- - -domainlab.tasks.a\_task\_classif module ---------------------------------------- - -.. automodule:: domainlab.tasks.a_task_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.b\_task module ------------------------------- - -.. automodule:: domainlab.tasks.b_task - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_folder module ------------------------------------ - -.. automodule:: domainlab.tasks.task_folder - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_folder\_mk module ---------------------------------------- - -.. automodule:: domainlab.tasks.task_folder_mk - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_mnist\_color module ------------------------------------------ - -.. automodule:: domainlab.tasks.task_mnist_color - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_pathlist module -------------------------------------- - -.. automodule:: domainlab.tasks.task_pathlist - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_utils module ----------------------------------- - -.. automodule:: domainlab.tasks.task_utils - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.utils\_task module ----------------------------------- - -.. automodule:: domainlab.tasks.utils_task - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.utils\_task\_dset module ----------------------------------------- - -.. automodule:: domainlab.tasks.utils_task_dset - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.zoo\_tasks module ---------------------------------- - -.. automodule:: domainlab.tasks.zoo_tasks - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.tasks - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/domainlab.utils.rst.txt b/docs/build/html/_sources/domainlab.utils.rst.txt deleted file mode 100644 index 5304491ea..000000000 --- a/docs/build/html/_sources/domainlab.utils.rst.txt +++ /dev/null @@ -1,125 +0,0 @@ -domainlab.utils package -======================= - -Submodules ----------- - -domainlab.utils.flows\_gen\_img\_model module ---------------------------------------------- - -.. automodule:: domainlab.utils.flows_gen_img_model - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.generate\_benchmark\_plots module -------------------------------------------------- - -.. automodule:: domainlab.utils.generate_benchmark_plots - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.get\_git\_tag module ------------------------------------- - -.. automodule:: domainlab.utils.get_git_tag - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.hyperparameter\_sampling module ------------------------------------------------ - -.. automodule:: domainlab.utils.hyperparameter_sampling - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.override\_interface module ------------------------------------------- - -.. automodule:: domainlab.utils.override_interface - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.perf module ---------------------------- - -.. automodule:: domainlab.utils.perf - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.perf\_metrics module ------------------------------------- - -.. automodule:: domainlab.utils.perf_metrics - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.test\_img module --------------------------------- - -.. automodule:: domainlab.utils.test_img - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.u\_import module --------------------------------- - -.. automodule:: domainlab.utils.u_import - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.u\_import\_net\_module module ---------------------------------------------- - -.. automodule:: domainlab.utils.u_import_net_module - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_class module ------------------------------------ - -.. automodule:: domainlab.utils.utils_class - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_classif module -------------------------------------- - -.. automodule:: domainlab.utils.utils_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_cuda module ----------------------------------- - -.. automodule:: domainlab.utils.utils_cuda - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_img\_sav module --------------------------------------- - -.. automodule:: domainlab.utils.utils_img_sav - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt deleted file mode 100644 index 90fa673a2..000000000 --- a/docs/build/html/_sources/index.rst.txt +++ /dev/null @@ -1,25 +0,0 @@ -.. domainlab documentation master file, created by - sphinx-quickstart on Tue Jul 26 16:30:46 2022. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to domainlab's documentation! -===================================== - -.. toctree:: - :maxdepth: 3 - :caption: Contents: - - modules - doc_algos - docHDUVA - docJiGen - doc_diva - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/build/html/_sources/modules.rst.txt b/docs/build/html/_sources/modules.rst.txt deleted file mode 100644 index 905205f31..000000000 --- a/docs/build/html/_sources/modules.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -domainlab -========= - -.. toctree:: - :maxdepth: 4 - - domainlab diff --git a/docs/build/html/_sources/readme_link.rst.txt b/docs/build/html/_sources/readme_link.rst.txt deleted file mode 100644 index 670387ceb..000000000 --- a/docs/build/html/_sources/readme_link.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ ----------------------- -Introduction ----------------------- - -.. include:: ../README.md - :parser: myst_parser.sphinx_ diff --git a/docs/build/html/_sources/requirements.txt b/docs/build/html/_sources/requirements.txt deleted file mode 100644 index 427ce1ad6..000000000 --- a/docs/build/html/_sources/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -linkify-it-py -m2r2 -myst-parser -rinohtype -nbsphinx -nbsphinx_link -sphinx_material -commonmark -# recommonmark==0.5.0.dev0 -git+https://github.com/rtfd/recommonmark diff --git a/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js b/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js deleted file mode 100644 index 8549469dc..000000000 --- a/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js +++ /dev/null @@ -1,134 +0,0 @@ -/* - * _sphinx_javascript_frameworks_compat.js - * ~~~~~~~~~~ - * - * Compatability shim for jQuery and underscores.js. - * - * WILL BE REMOVED IN Sphinx 6.0 - * xref RemovedInSphinx60Warning - * - */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x - } - return decodeURIComponent(x.replace(/\+/g, ' ')); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css deleted file mode 100644 index 088967717..000000000 --- a/docs/build/html/_static/basic.css +++ /dev/null @@ -1,930 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -div.section::after { - display: block; - content: ''; - clear: left; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox form.search { - overflow: hidden; -} - -div.sphinxsidebar #searchbox input[type="text"] { - float: left; - width: 80%; - padding: 0.25em; - box-sizing: border-box; -} - -div.sphinxsidebar #searchbox input[type="submit"] { - float: left; - width: 20%; - border-left: none; - padding: 0.25em; - box-sizing: border-box; -} - - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li p.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body { - min-width: 360px; - max-width: 800px; -} - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, figure.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, figure.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, figure.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -img.align-default, figure.align-default, .figure.align-default { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-default { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar, -aside.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px; - background-color: #ffe; - width: 40%; - float: right; - clear: right; - overflow-x: auto; -} - -p.sidebar-title { - font-weight: bold; -} -nav.contents, -aside.topic, - -div.admonition, div.topic, blockquote { - clear: left; -} - -/* -- topics ---------------------------------------------------------------- */ -nav.contents, -aside.topic, - -div.topic { - border: 1px solid #ccc; - padding: 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -aside.sidebar > :last-child, -nav.contents > :last-child, -aside.topic > :last-child, - -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -aside.sidebar::after, -nav.contents::after, -aside.topic::after, - -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - margin-top: 10px; - margin-bottom: 10px; - border: 0; - border-collapse: collapse; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -table.align-default { - margin-left: auto; - margin-right: auto; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -th > :first-child, -td > :first-child { - margin-top: 0px; -} - -th > :last-child, -td > :last-child { - margin-bottom: 0px; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure, figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption, figcaption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number, -figcaption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text, -figcaption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- hlist styles ---------------------------------------------------------- */ - -table.hlist { - margin: 1em 0; -} - -table.hlist td { - vertical-align: top; -} - -/* -- object description styles --------------------------------------------- */ - -.sig { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; -} - -.sig-name, code.descname { - background-color: transparent; - font-weight: bold; -} - -.sig-name { - font-size: 1.1em; -} - -code.descname { - font-size: 1.2em; -} - -.sig-prename, code.descclassname { - background-color: transparent; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.sig-param.n { - font-style: italic; -} - -/* C++ specific styling */ - -.sig-inline.c-texpr, -.sig-inline.cpp-texpr { - font-family: unset; -} - -.sig.c .k, .sig.c .kt, -.sig.cpp .k, .sig.cpp .kt { - color: #0033B3; -} - -.sig.c .m, -.sig.cpp .m { - color: #1750EB; -} - -.sig.c .s, .sig.c .sc, -.sig.cpp .s, .sig.cpp .sc { - color: #067D17; -} - - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { - margin-top: 0px; -} - -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { - margin-bottom: 0px; -} - -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - -/* Docutils 0.17 and older (footnotes & citations) */ -dl.footnote > dt, -dl.citation > dt { - float: left; - margin-right: 0.5em; -} - -dl.footnote > dd, -dl.citation > dd { - margin-bottom: 0em; -} - -dl.footnote > dd:after, -dl.citation > dd:after { - content: ""; - clear: both; -} - -/* Docutils 0.18+ (footnotes & citations) */ -aside.footnote > span, -div.citation > span { - float: left; -} -aside.footnote > span:last-of-type, -div.citation > span:last-of-type { - padding-right: 0.5em; -} -aside.footnote > p { - margin-left: 2em; -} -div.citation > p { - margin-left: 4em; -} -aside.footnote > p:last-of-type, -div.citation > p:last-of-type { - margin-bottom: 0em; -} -aside.footnote > p:last-of-type:after, -div.citation > p:last-of-type:after { - content: ""; - clear: both; -} - -/* Footnotes & citations ends */ - -dl.field-list { - display: grid; - grid-template-columns: fit-content(30%) auto; -} - -dl.field-list > dt { - font-weight: bold; - word-break: break-word; - padding-left: 0.5em; - padding-right: 5px; -} - -dl.field-list > dt:after { - content: ":"; -} - -dl.field-list > dd { - padding-left: 0.5em; - margin-top: 0em; - margin-left: 0em; - margin-bottom: 0em; -} - -dl { - margin-bottom: 15px; -} - -dd > :first-child { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - -dt:target, span.highlighted { - background-color: #fbe54e; -} - -rect.highlighted { - fill: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -.classifier:before { - font-style: normal; - margin: 0 0.5em; - content: ":"; - display: inline-block; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -pre, div[class*="highlight-"] { - clear: both; -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; - white-space: nowrap; -} - -div[class*="highlight-"] { - margin: 1em 0; -} - -td.linenos pre { - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; -} - -table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; -} - -div.code-block-caption { - margin-top: 1em; - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -table.highlighttable td.linenos, -span.linenos, -div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; - -webkit-user-select: text; /* Safari fallback only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - margin: 1em 0; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: absolute; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js deleted file mode 100644 index c3db08d1c..000000000 --- a/docs/build/html/_static/doctools.js +++ /dev/null @@ -1,264 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Base JavaScript utilities for all Sphinx HTML documentation. - * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ -"use strict"; - -const _ready = (callback) => { - if (document.readyState !== "loading") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } -}; - -/** - * highlight a given string on a node by wrapping it in - * span elements with the given class name. - */ -const _highlight = (node, addItems, text, className) => { - if (node.nodeType === Node.TEXT_NODE) { - const val = node.nodeValue; - const parent = node.parentNode; - const pos = val.toLowerCase().indexOf(text); - if ( - pos >= 0 && - !parent.classList.contains(className) && - !parent.classList.contains("nohighlight") - ) { - let span; - - const closestNode = parent.closest("body, svg, foreignObject"); - const isInSVG = closestNode && closestNode.matches("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.classList.add(className); - } - - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - parent.insertBefore( - span, - parent.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling - ) - ); - node.nodeValue = val.substr(0, pos); - - if (isInSVG) { - const rect = document.createElementNS( - "http://www.w3.org/2000/svg", - "rect" - ); - const bbox = parent.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute("class", className); - addItems.push({ parent: parent, target: rect }); - } - } - } else if (node.matches && !node.matches("button, select, textarea")) { - node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); - } -}; -const _highlightText = (thisNode, text, className) => { - let addItems = []; - _highlight(thisNode, addItems, text, className); - addItems.forEach((obj) => - obj.parent.insertAdjacentElement("beforebegin", obj.target) - ); -}; - -/** - * Small JavaScript module for the documentation. - */ -const Documentation = { - init: () => { - Documentation.highlightSearchWords(); - Documentation.initDomainIndexTable(); - Documentation.initOnKeyListeners(); - }, - - /** - * i18n support - */ - TRANSLATIONS: {}, - PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), - LOCALE: "unknown", - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext: (string) => { - const translated = Documentation.TRANSLATIONS[string]; - switch (typeof translated) { - case "undefined": - return string; // no translation - case "string": - return translated; // translation exists - default: - return translated[0]; // (singular, plural) translation tuple exists - } - }, - - ngettext: (singular, plural, n) => { - const translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated !== "undefined") - return translated[Documentation.PLURAL_EXPR(n)]; - return n === 1 ? singular : plural; - }, - - addTranslations: (catalog) => { - Object.assign(Documentation.TRANSLATIONS, catalog.messages); - Documentation.PLURAL_EXPR = new Function( - "n", - `return (${catalog.plural_expr})` - ); - Documentation.LOCALE = catalog.locale; - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords: () => { - const highlight = - new URLSearchParams(window.location.search).get("highlight") || ""; - const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); - if (terms.length === 0) return; // nothing to do - - // There should never be more than one element matching "div.body" - const divBody = document.querySelectorAll("div.body"); - const body = divBody.length ? divBody[0] : document.querySelector("body"); - window.setTimeout(() => { - terms.forEach((term) => _highlightText(body, term, "highlighted")); - }, 10); - - const searchBox = document.getElementById("searchbox"); - if (searchBox === null) return; - searchBox.appendChild( - document - .createRange() - .createContextualFragment( - '" - ) - ); - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords: () => { - document - .querySelectorAll("#searchbox .highlight-link") - .forEach((el) => el.remove()); - document - .querySelectorAll("span.highlighted") - .forEach((el) => el.classList.remove("highlighted")); - const url = new URL(window.location); - url.searchParams.delete("highlight"); - window.history.replaceState({}, "", url); - }, - - /** - * helper function to focus on search bar - */ - focusSearchBar: () => { - document.querySelectorAll("input[name=q]")[0]?.focus(); - }, - - /** - * Initialise the domain index toggle buttons - */ - initDomainIndexTable: () => { - const toggler = (el) => { - const idNumber = el.id.substr(7); - const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); - if (el.src.substr(-9) === "minus.png") { - el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; - toggledRows.forEach((el) => (el.style.display = "none")); - } else { - el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; - toggledRows.forEach((el) => (el.style.display = "")); - } - }; - - const togglerElements = document.querySelectorAll("img.toggler"); - togglerElements.forEach((el) => - el.addEventListener("click", (event) => toggler(event.currentTarget)) - ); - togglerElements.forEach((el) => (el.style.display = "")); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); - }, - - initOnKeyListeners: () => { - // only install a listener if it is really needed - if ( - !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS - ) - return; - - const blacklistedElements = new Set([ - "TEXTAREA", - "INPUT", - "SELECT", - "BUTTON", - ]); - document.addEventListener("keydown", (event) => { - if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements - if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys - - if (!event.shiftKey) { - switch (event.key) { - case "ArrowLeft": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const prevLink = document.querySelector('link[rel="prev"]'); - if (prevLink && prevLink.href) { - window.location.href = prevLink.href; - event.preventDefault(); - } - break; - case "ArrowRight": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const nextLink = document.querySelector('link[rel="next"]'); - if (nextLink && nextLink.href) { - window.location.href = nextLink.href; - event.preventDefault(); - } - break; - case "Escape": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.hideSearchWords(); - event.preventDefault(); - } - } - - // some keyboard layouts may need Shift to get / - switch (event.key) { - case "/": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.focusSearchBar(); - event.preventDefault(); - } - }); - }, -}; - -// quick alias for translations -const _ = Documentation.gettext; - -_ready(Documentation.init); diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js deleted file mode 100644 index a750e4d5e..000000000 --- a/docs/build/html/_static/documentation_options.js +++ /dev/null @@ -1,14 +0,0 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '', - LANGUAGE: 'en', - COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false, - SHOW_SEARCH_SUMMARY: true, - ENABLE_SEARCH_SHORTCUTS: false, -}; \ No newline at end of file diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png deleted file mode 100644 index a858a410e..000000000 Binary files a/docs/build/html/_static/file.png and /dev/null differ diff --git a/docs/build/html/_static/fonts/font-awesome.css b/docs/build/html/_static/fonts/font-awesome.css deleted file mode 100644 index b476b53e3..000000000 --- a/docs/build/html/_static/fonts/font-awesome.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url("specimen/FontAwesome.woff2") format("woff2"),url("specimen/FontAwesome.woff") format("woff"),url("specimen/FontAwesome.ttf") format("truetype")}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} \ No newline at end of file diff --git a/docs/build/html/_static/fonts/material-icons.css b/docs/build/html/_static/fonts/material-icons.css deleted file mode 100644 index 63130b012..000000000 --- a/docs/build/html/_static/fonts/material-icons.css +++ /dev/null @@ -1,13 +0,0 @@ -/*! - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE - * DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - * SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND - * LIMITATIONS UNDER THE LICENSE. - */@font-face{font-display:swap;font-family:"Material Icons";font-style:normal;font-weight:400;src:local("Material Icons"),local("MaterialIcons-Regular"),url("specimen/MaterialIcons-Regular.woff2") format("woff2"),url("specimen/MaterialIcons-Regular.woff") format("woff"),url("specimen/MaterialIcons-Regular.ttf") format("truetype")} \ No newline at end of file diff --git a/docs/build/html/_static/fonts/specimen/FontAwesome.ttf b/docs/build/html/_static/fonts/specimen/FontAwesome.ttf deleted file mode 100644 index 35acda2fa..000000000 Binary files a/docs/build/html/_static/fonts/specimen/FontAwesome.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/specimen/FontAwesome.woff b/docs/build/html/_static/fonts/specimen/FontAwesome.woff deleted file mode 100644 index 400014a4b..000000000 Binary files a/docs/build/html/_static/fonts/specimen/FontAwesome.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/specimen/FontAwesome.woff2 b/docs/build/html/_static/fonts/specimen/FontAwesome.woff2 deleted file mode 100644 index 4d13fc604..000000000 Binary files a/docs/build/html/_static/fonts/specimen/FontAwesome.woff2 and /dev/null differ diff --git a/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.ttf b/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.ttf deleted file mode 100644 index 7015564ad..000000000 Binary files a/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.woff b/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.woff deleted file mode 100644 index b648a3eea..000000000 Binary files a/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.woff2 b/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.woff2 deleted file mode 100644 index 9fa211252..000000000 Binary files a/docs/build/html/_static/fonts/specimen/MaterialIcons-Regular.woff2 and /dev/null differ diff --git a/docs/build/html/_static/images/favicon.png b/docs/build/html/_static/images/favicon.png deleted file mode 100644 index 76d17f57a..000000000 Binary files a/docs/build/html/_static/images/favicon.png and /dev/null differ diff --git a/docs/build/html/_static/images/icons/bitbucket.1b09e088.svg b/docs/build/html/_static/images/icons/bitbucket.1b09e088.svg deleted file mode 100644 index cf58c14fb..000000000 --- a/docs/build/html/_static/images/icons/bitbucket.1b09e088.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/build/html/_static/images/icons/bitbucket.svg b/docs/build/html/_static/images/icons/bitbucket.svg deleted file mode 100644 index cf58c14fb..000000000 --- a/docs/build/html/_static/images/icons/bitbucket.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/build/html/_static/images/icons/github.f0b8504a.svg b/docs/build/html/_static/images/icons/github.f0b8504a.svg deleted file mode 100644 index 3d13b1975..000000000 --- a/docs/build/html/_static/images/icons/github.f0b8504a.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/build/html/_static/images/icons/github.svg b/docs/build/html/_static/images/icons/github.svg deleted file mode 100644 index 3d13b1975..000000000 --- a/docs/build/html/_static/images/icons/github.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/build/html/_static/images/icons/gitlab.6dd19c00.svg b/docs/build/html/_static/images/icons/gitlab.6dd19c00.svg deleted file mode 100644 index 1d9fffa74..000000000 --- a/docs/build/html/_static/images/icons/gitlab.6dd19c00.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/build/html/_static/images/icons/gitlab.svg b/docs/build/html/_static/images/icons/gitlab.svg deleted file mode 100644 index 1d9fffa74..000000000 --- a/docs/build/html/_static/images/icons/gitlab.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/application.js b/docs/build/html/_static/javascripts/application.js deleted file mode 100644 index 7c724d2e4..000000000 --- a/docs/build/html/_static/javascripts/application.js +++ /dev/null @@ -1,2540 +0,0 @@ -! function(e, t) { - for (var n in t) e[n] = t[n] -}(window, function(n) { - var r = {}; - - function i(e) { - if (r[e]) return r[e].exports; - var t = r[e] = { - i: e, - l: !1, - exports: {} - }; - return n[e].call(t.exports, t, t.exports, i), t.l = !0, t.exports - } - return i.m = n, i.c = r, i.d = function(e, t, n) { - i.o(e, t) || Object.defineProperty(e, t, { - enumerable: !0, - get: n - }) - }, i.r = function(e) { - "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { - value: "Module" - }), Object.defineProperty(e, "__esModule", { - value: !0 - }) - }, i.t = function(t, e) { - if (1 & e && (t = i(t)), 8 & e) return t; - if (4 & e && "object" == typeof t && t && t.__esModule) return t; - var n = Object.create(null); - if (i.r(n), Object.defineProperty(n, "default", { - enumerable: !0, - value: t - }), 2 & e && "string" != typeof t) - for (var r in t) i.d(n, r, function(e) { - return t[e] - }.bind(null, r)); - return n - }, i.n = function(e) { - var t = e && e.__esModule ? function() { - return e.default - } : function() { - return e - }; - return i.d(t, "a", t), t - }, i.o = function(e, t) { - return Object.prototype.hasOwnProperty.call(e, t) - }, i.p = "", i(i.s = 13) -}([function(e, t, n) { - "use strict"; - var r = { - Listener: function() { - function e(e, t, n) { - var r = this; - this.els_ = Array.prototype.slice.call("string" == typeof e ? document.querySelectorAll(e) : [].concat(e)), this.handler_ = "function" == typeof n ? { - update: n - } : n, this.events_ = [].concat(t), this.update_ = function(e) { - return r.handler_.update(e) - } - } - var t = e.prototype; - return t.listen = function() { - var n = this; - this.els_.forEach(function(t) { - n.events_.forEach(function(e) { - t.addEventListener(e, n.update_, !1) - }) - }), "function" == typeof this.handler_.setup && this.handler_.setup() - }, t.unlisten = function() { - var n = this; - this.els_.forEach(function(t) { - n.events_.forEach(function(e) { - t.removeEventListener(e, n.update_) - }) - }), "function" == typeof this.handler_.reset && this.handler_.reset() - }, e - }(), - MatchMedia: function(e, t) { - this.handler_ = function(e) { - e.matches ? t.listen() : t.unlisten() - }; - var n = window.matchMedia(e); - n.addListener(this.handler_), this.handler_(n) - } - }, - i = { - Shadow: function() { - function e(e, t) { - var n = "string" == typeof e ? document.querySelector(e) : e; - if (!(n instanceof HTMLElement && n.parentNode instanceof HTMLElement)) throw new ReferenceError; - if (this.el_ = n.parentNode, !((n = "string" == typeof t ? document.querySelector(t) : t) instanceof HTMLElement)) throw new ReferenceError; - this.header_ = n, this.height_ = 0, this.active_ = !1 - } - var t = e.prototype; - return t.setup = function() { - for (var e = this.el_; e = e.previousElementSibling;) { - if (!(e instanceof HTMLElement)) throw new ReferenceError; - this.height_ += e.offsetHeight - } - this.update() - }, t.update = function(e) { - if (!e || "resize" !== e.type && "orientationchange" !== e.type) { - var t = window.pageYOffset >= this.height_; - t !== this.active_ && (this.header_.dataset.mdState = (this.active_ = t) ? "shadow" : "") - } else this.height_ = 0, this.setup() - }, t.reset = function() { - this.header_.dataset.mdState = "", this.height_ = 0, this.active_ = !1 - }, e - }(), - Title: function() { - function e(e, t) { - var n = "string" == typeof e ? document.querySelector(e) : e; - if (!(n instanceof HTMLElement)) throw new ReferenceError; - if (this.el_ = n, !((n = "string" == typeof t ? document.querySelector(t) : t) instanceof HTMLHeadingElement)) throw new ReferenceError; - this.header_ = n, this.active_ = !1 - } - var t = e.prototype; - return t.setup = function() { - var t = this; - Array.prototype.forEach.call(this.el_.children, function(e) { - e.style.width = t.el_.offsetWidth - 20 + "px" - }) - }, t.update = function(e) { - var t = this, - n = window.pageYOffset >= this.header_.offsetTop; - n !== this.active_ && (this.el_.dataset.mdState = (this.active_ = n) ? "active" : ""), "resize" !== e.type && "orientationchange" !== e.type || Array.prototype.forEach.call(this.el_.children, function(e) { - e.style.width = t.el_.offsetWidth - 20 + "px" - }) - }, t.reset = function() { - this.el_.dataset.mdState = "", this.el_.style.width = "", this.active_ = !1 - }, e - }() - }, - o = { - Blur: function() { - function e(e) { - this.els_ = "string" == typeof e ? document.querySelectorAll(e) : e, this.index_ = 0, this.offset_ = window.pageYOffset, this.dir_ = !1, this.anchors_ = [].reduce.call(this.els_, function(e, t) { - var n = decodeURIComponent(t.hash); - return e.concat(document.getElementById(n.substring(1)) || []) - }, []) - } - var t = e.prototype; - return t.setup = function() { - this.update() - }, t.update = function() { - var e = window.pageYOffset, - t = this.offset_ - e < 0; - if (this.dir_ !== t && (this.index_ = this.index_ = t ? 0 : this.els_.length - 1), 0 !== this.anchors_.length) { - if (this.offset_ <= e) - for (var n = this.index_ + 1; n < this.els_.length && this.anchors_[n].offsetTop - 80 <= e; n++) 0 < n && (this.els_[n - 1].dataset.mdState = "blur"), this.index_ = n; - else - for (var r = this.index_; 0 <= r; r--) { - if (!(this.anchors_[r].offsetTop - 80 > e)) { - this.index_ = r; - break - } - 0 < r && (this.els_[r - 1].dataset.mdState = "") - } - this.offset_ = e, this.dir_ = t - } - }, t.reset = function() { - Array.prototype.forEach.call(this.els_, function(e) { - e.dataset.mdState = "" - }), this.index_ = 0, this.offset_ = window.pageYOffset - }, e - }(), - Collapse: function() { - function e(e) { - var t = "string" == typeof e ? document.querySelector(e) : e; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - this.el_ = t - } - var t = e.prototype; - return t.setup = function() { - var e = this.el_.getBoundingClientRect().height; - this.el_.style.display = e ? "block" : "none", this.el_.style.overflow = e ? "visible" : "hidden" - }, t.update = function() { - var e = this, - t = this.el_.getBoundingClientRect().height; - this.el_.style.display = "block", this.el_.style.overflow = ""; - var r = this.el_.previousElementSibling.previousElementSibling.checked; - if (r) this.el_.style.maxHeight = t + "px", requestAnimationFrame(function() { - e.el_.setAttribute("data-md-state", "animate"), e.el_.style.maxHeight = "0px" - }); - else { - this.el_.setAttribute("data-md-state", "expand"), this.el_.style.maxHeight = ""; - var n = this.el_.getBoundingClientRect().height; - this.el_.removeAttribute("data-md-state"), this.el_.style.maxHeight = "0px", requestAnimationFrame(function() { - e.el_.setAttribute("data-md-state", "animate"), e.el_.style.maxHeight = n + "px" - }) - } - this.el_.addEventListener("transitionend", function e(t) { - var n = t.target; - if (!(n instanceof HTMLElement)) throw new ReferenceError; - n.removeAttribute("data-md-state"), n.style.maxHeight = "", n.style.display = r ? "none" : "block", n.style.overflow = r ? "hidden" : "visible", n.removeEventListener("transitionend", e) - }, !1) - }, t.reset = function() { - this.el_.dataset.mdState = "", this.el_.style.maxHeight = "", this.el_.style.display = "", this.el_.style.overflow = "" - }, e - }(), - Scrolling: function() { - function e(e) { - var t = "string" == typeof e ? document.querySelector(e) : e; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - this.el_ = t - } - var t = e.prototype; - return t.setup = function() { - this.el_.children[this.el_.children.length - 1].style.webkitOverflowScrolling = "touch"; - var e = this.el_.querySelectorAll("[data-md-toggle]"); - Array.prototype.forEach.call(e, function(e) { - if (!(e instanceof HTMLInputElement)) throw new ReferenceError; - if (e.checked) { - var t = e.nextElementSibling; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - for (; - "NAV" !== t.tagName && t.nextElementSibling;) t = t.nextElementSibling; - if (!(e.parentNode instanceof HTMLElement && e.parentNode.parentNode instanceof HTMLElement)) throw new ReferenceError; - var n = e.parentNode.parentNode, - r = t.children[t.children.length - 1]; - n.style.webkitOverflowScrolling = "", r.style.webkitOverflowScrolling = "touch" - } - }) - }, t.update = function(e) { - var t = e.target; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - var n = t.nextElementSibling; - if (!(n instanceof HTMLElement)) throw new ReferenceError; - for (; - "NAV" !== n.tagName && n.nextElementSibling;) n = n.nextElementSibling; - if (!(t.parentNode instanceof HTMLElement && t.parentNode.parentNode instanceof HTMLElement)) throw new ReferenceError; - var r = t.parentNode.parentNode, - i = n.children[n.children.length - 1]; - if (r.style.webkitOverflowScrolling = "", i.style.webkitOverflowScrolling = "", !t.checked) { - n.addEventListener("transitionend", function e() { - n instanceof HTMLElement && (r.style.webkitOverflowScrolling = "touch", n.removeEventListener("transitionend", e)) - }, !1) - } - if (t.checked) { - n.addEventListener("transitionend", function e() { - n instanceof HTMLElement && (i.style.webkitOverflowScrolling = "touch", n.removeEventListener("transitionend", e)) - }, !1) - } - }, t.reset = function() { - this.el_.children[1].style.webkitOverflowScrolling = ""; - var e = this.el_.querySelectorAll("[data-md-toggle]"); - Array.prototype.forEach.call(e, function(e) { - if (!(e instanceof HTMLInputElement)) throw new ReferenceError; - if (e.checked) { - var t = e.nextElementSibling; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - for (; - "NAV" !== t.tagName && t.nextElementSibling;) t = t.nextElementSibling; - if (!(e.parentNode instanceof HTMLElement && e.parentNode.parentNode instanceof HTMLElement)) throw new ReferenceError; - var n = e.parentNode.parentNode, - r = t.children[t.children.length - 1]; - n.style.webkitOverflowScrolling = "", r.style.webkitOverflowScrolling = "" - } - }) - }, e - }() - }, - a = { - Lock: function() { - function e(e) { - var t = "string" == typeof e ? document.querySelector(e) : e; - if (!(t instanceof HTMLInputElement)) throw new ReferenceError; - if (this.el_ = t, !document.body) throw new ReferenceError; - this.lock_ = document.body - } - var t = e.prototype; - return t.setup = function() { - this.update() - }, t.update = function() { - var e = this; - this.el_.checked ? (this.offset_ = window.pageYOffset, setTimeout(function() { - window.scrollTo(0, 0), e.el_.checked && (e.lock_.dataset.mdState = "lock") - }, 400)) : (this.lock_.dataset.mdState = "", setTimeout(function() { - void 0 !== e.offset_ && window.scrollTo(0, e.offset_) - }, 100)) - }, t.reset = function() { - "lock" === this.lock_.dataset.mdState && window.scrollTo(0, this.offset_), this.lock_.dataset.mdState = "" - }, e - }(), - Result: n(9).a - }, - s = { - Position: function() { - function e(e, t) { - var n = "string" == typeof e ? document.querySelector(e) : e; - if (!(n instanceof HTMLElement && n.parentNode instanceof HTMLElement)) throw new ReferenceError; - if (this.el_ = n, this.parent_ = n.parentNode, !((n = "string" == typeof t ? document.querySelector(t) : t) instanceof HTMLElement)) throw new ReferenceError; - this.header_ = n, this.height_ = 0, this.pad_ = "fixed" === window.getComputedStyle(this.header_).position - } - var t = e.prototype; - return t.setup = function() { - var e = Array.prototype.reduce.call(this.parent_.children, function(e, t) { - return Math.max(e, t.offsetTop) - }, 0); - this.offset_ = e - (this.pad_ ? this.header_.offsetHeight : 0), this.update() - }, t.update = function(e) { - var t = window.pageYOffset, - n = window.innerHeight; - e && "resize" === e.type && this.setup(); - var r = this.pad_ ? this.header_.offsetHeight : 0, - i = this.parent_.offsetTop + this.parent_.offsetHeight, - o = n - r - Math.max(0, this.offset_ - t) - Math.max(0, t + n - i); - o !== this.height_ && (this.el_.style.height = (this.height_ = o) + "px"), t >= this.offset_ ? "lock" !== this.el_.dataset.mdState && (this.el_.dataset.mdState = "lock") : "lock" === this.el_.dataset.mdState && (this.el_.dataset.mdState = "") - }, t.reset = function() { - this.el_.dataset.mdState = "", this.el_.style.height = "", this.height_ = 0 - }, e - }() - }, - c = n(6), - l = n.n(c); - var u = { - Adapter: { - GitHub: function(o) { - var e, t; - - function n(e) { - var t; - t = o.call(this, e) || this; - var n = /^.+github\.com\/([^/]+)\/?([^/]+)?.*$/.exec(t.base_); - if (n && 3 === n.length) { - var r = n[1], - i = n[2]; - t.base_ = "https://api.github.com/users/" + r + "/repos", t.name_ = i - } - return t - } - return t = o, (e = n).prototype = Object.create(t.prototype), (e.prototype.constructor = e).__proto__ = t, n.prototype.fetch_ = function() { - var i = this; - return function n(r) { - return void 0 === r && (r = 0), fetch(i.base_ + "?per_page=30&page=" + r).then(function(e) { - return e.json() - }).then(function(e) { - if (!(e instanceof Array)) throw new TypeError; - if (i.name_) { - var t = e.find(function(e) { - return e.name === i.name_ - }); - return t || 30 !== e.length ? t ? [i.format_(t.stargazers_count) + " Stars", i.format_(t.forks_count) + " Forks"] : [] : n(r + 1) - } - return [e.length + " Repositories"] - }) - }() - }, n - }(function() { - function e(e) { - var t = "string" == typeof e ? document.querySelector(e) : e; - if (!(t instanceof HTMLAnchorElement)) throw new ReferenceError; - this.el_ = t, this.base_ = this.el_.href, this.salt_ = this.hash_(this.base_) - } - var t = e.prototype; - return t.fetch = function() { - var n = this; - return new Promise(function(t) { - var e = l.a.getJSON(n.salt_ + ".cache-source"); - void 0 !== e ? t(e) : n.fetch_().then(function(e) { - l.a.set(n.salt_ + ".cache-source", e, { - expires: 1 / 96 - }), t(e) - }) - }) - }, t.fetch_ = function() { - throw new Error("fetch_(): Not implemented") - }, t.format_ = function(e) { - return 1e4 < e ? (e / 1e3).toFixed(0) + "k" : 1e3 < e ? (e / 1e3).toFixed(1) + "k" : "" + e - }, t.hash_ = function(e) { - var t = 0; - if (0 === e.length) return t; - for (var n = 0, r = e.length; n < r; n++) t = (t << 5) - t + e.charCodeAt(n), t |= 0; - return t - }, e - }()) - }, - Repository: n(10).a - }, - f = { - Toggle: function() { - function e(e) { - var t = "string" == typeof e ? document.querySelector(e) : e; - if (!(t instanceof Node)) throw new ReferenceError; - this.el_ = t; - var n = document.querySelector("[data-md-component=header]"); - this.height_ = n.offsetHeight, this.active_ = !1 - } - var t = e.prototype; - return t.update = function() { - var e = window.pageYOffset >= this.el_.children[0].offsetTop + (5 - this.height_); - e !== this.active_ && (this.el_.dataset.mdState = (this.active_ = e) ? "hidden" : "") - }, t.reset = function() { - this.el_.dataset.mdState = "", this.active_ = !1 - }, e - }() - }; - t.a = { - Event: r, - Header: i, - Nav: o, - Search: a, - Sidebar: s, - Source: u, - Tabs: f - } -}, function(t, e, n) { - (function(e) { - t.exports = e.lunr = n(24) - }).call(this, n(4)) -}, function(e, f, d) { - "use strict"; - (function(t) { - var e = d(8), - n = setTimeout; - - function r() {} - - function o(e) { - if (!(this instanceof o)) throw new TypeError("Promises must be constructed via new"); - if ("function" != typeof e) throw new TypeError("not a function"); - this._state = 0, this._handled = !1, this._value = void 0, this._deferreds = [], u(e, this) - } - - function i(n, r) { - for (; 3 === n._state;) n = n._value; - 0 !== n._state ? (n._handled = !0, o._immediateFn(function() { - var e = 1 === n._state ? r.onFulfilled : r.onRejected; - if (null !== e) { - var t; - try { - t = e(n._value) - } catch (e) { - return void s(r.promise, e) - } - a(r.promise, t) - } else(1 === n._state ? a : s)(r.promise, n._value) - })) : n._deferreds.push(r) - } - - function a(t, e) { - try { - if (e === t) throw new TypeError("A promise cannot be resolved with itself."); - if (e && ("object" == typeof e || "function" == typeof e)) { - var n = e.then; - if (e instanceof o) return t._state = 3, t._value = e, void c(t); - if ("function" == typeof n) return void u((r = n, i = e, function() { - r.apply(i, arguments) - }), t) - } - t._state = 1, t._value = e, c(t) - } catch (e) { - s(t, e) - } - var r, i - } - - function s(e, t) { - e._state = 2, e._value = t, c(e) - } - - function c(e) { - 2 === e._state && 0 === e._deferreds.length && o._immediateFn(function() { - e._handled || o._unhandledRejectionFn(e._value) - }); - for (var t = 0, n = e._deferreds.length; t < n; t++) i(e, e._deferreds[t]); - e._deferreds = null - } - - function l(e, t, n) { - this.onFulfilled = "function" == typeof e ? e : null, this.onRejected = "function" == typeof t ? t : null, this.promise = n - } - - function u(e, t) { - var n = !1; - try { - e(function(e) { - n || (n = !0, a(t, e)) - }, function(e) { - n || (n = !0, s(t, e)) - }) - } catch (e) { - if (n) return; - n = !0, s(t, e) - } - } - o.prototype.catch = function(e) { - return this.then(null, e) - }, o.prototype.then = function(e, t) { - var n = new this.constructor(r); - return i(this, new l(e, t, n)), n - }, o.prototype.finally = e.a, o.all = function(t) { - return new o(function(r, i) { - if (!t || void 0 === t.length) throw new TypeError("Promise.all accepts an array"); - var o = Array.prototype.slice.call(t); - if (0 === o.length) return r([]); - var a = o.length; - - function s(t, e) { - try { - if (e && ("object" == typeof e || "function" == typeof e)) { - var n = e.then; - if ("function" == typeof n) return void n.call(e, function(e) { - s(t, e) - }, i) - } - o[t] = e, 0 == --a && r(o) - } catch (e) { - i(e) - } - } - for (var e = 0; e < o.length; e++) s(e, o[e]) - }) - }, o.resolve = function(t) { - return t && "object" == typeof t && t.constructor === o ? t : new o(function(e) { - e(t) - }) - }, o.reject = function(n) { - return new o(function(e, t) { - t(n) - }) - }, o.race = function(i) { - return new o(function(e, t) { - for (var n = 0, r = i.length; n < r; n++) i[n].then(e, t) - }) - }, o._immediateFn = "function" == typeof t && function(e) { - t(e) - } || function(e) { - n(e, 0) - }, o._unhandledRejectionFn = function(e) { - "undefined" != typeof console && console && console.warn("Possible Unhandled Promise Rejection:", e) - }, f.a = o - }).call(this, d(21).setImmediate) -}, function(e, t, n) { - "use strict"; - - function r(e, t) { - var n = document.createElement(e); - t && Array.prototype.forEach.call(Object.keys(t), function(e) { - n.setAttribute(e, t[e]) - }); - for (var r = arguments.length, i = new Array(2 < r ? r - 2 : 0), o = 2; o < r; o++) i[o - 2] = arguments[o]; - return function t(e) { - Array.prototype.forEach.call(e, function(e) { - "string" == typeof e || "number" == typeof e ? n.textContent += e : Array.isArray(e) ? t(e) : void 0 !== e.__html ? n.innerHTML += e.__html : e instanceof Node && n.appendChild(e) - }) - }(i), n - } - n.r(t), n.d(t, "createElement", function() { - return r - }) -}, function(e, t) { - var n; - n = function() { - return this - }(); - try { - n = n || new Function("return this")() - } catch (e) { - "object" == typeof window && (n = window) - } - e.exports = n -}, function(e, t, n) { - var r; - r = function() { - return function(n) { - var r = {}; - - function i(e) { - if (r[e]) return r[e].exports; - var t = r[e] = { - i: e, - l: !1, - exports: {} - }; - return n[e].call(t.exports, t, t.exports, i), t.l = !0, t.exports - } - return i.m = n, i.c = r, i.d = function(e, t, n) { - i.o(e, t) || Object.defineProperty(e, t, { - enumerable: !0, - get: n - }) - }, i.r = function(e) { - "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { - value: "Module" - }), Object.defineProperty(e, "__esModule", { - value: !0 - }) - }, i.t = function(t, e) { - if (1 & e && (t = i(t)), 8 & e) return t; - if (4 & e && "object" == typeof t && t && t.__esModule) return t; - var n = Object.create(null); - if (i.r(n), Object.defineProperty(n, "default", { - enumerable: !0, - value: t - }), 2 & e && "string" != typeof t) - for (var r in t) i.d(n, r, function(e) { - return t[e] - }.bind(null, r)); - return n - }, i.n = function(e) { - var t = e && e.__esModule ? function() { - return e.default - } : function() { - return e - }; - return i.d(t, "a", t), t - }, i.o = function(e, t) { - return Object.prototype.hasOwnProperty.call(e, t) - }, i.p = "", i(i.s = 0) - }([function(e, t, n) { - "use strict"; - var i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(e) { - return typeof e - } : function(e) { - return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e - }, - o = function() { - function r(e, t) { - for (var n = 0; n < t.length; n++) { - var r = t[n]; - r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r) - } - } - return function(e, t, n) { - return t && r(e.prototype, t), n && r(e, n), e - } - }(), - a = r(n(1)), - s = r(n(3)), - c = r(n(4)); - - function r(e) { - return e && e.__esModule ? e : { - default: e - } - } - var l = function(e) { - function r(e, t) { - ! function(e, t) { - if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function") - }(this, r); - var n = function(e, t) { - if (!e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - return !t || "object" != typeof t && "function" != typeof t ? e : t - }(this, (r.__proto__ || Object.getPrototypeOf(r)).call(this)); - return n.resolveOptions(t), n.listenClick(e), n - } - return function(e, t) { - if ("function" != typeof t && null !== t) throw new TypeError("Super expression must either be null or a function, not " + typeof t); - e.prototype = Object.create(t && t.prototype, { - constructor: { - value: e, - enumerable: !1, - writable: !0, - configurable: !0 - } - }), t && (Object.setPrototypeOf ? Object.setPrototypeOf(e, t) : e.__proto__ = t) - }(r, s.default), o(r, [{ - key: "resolveOptions", - value: function() { - var e = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}; - this.action = "function" == typeof e.action ? e.action : this.defaultAction, this.target = "function" == typeof e.target ? e.target : this.defaultTarget, this.text = "function" == typeof e.text ? e.text : this.defaultText, this.container = "object" === i(e.container) ? e.container : document.body - } - }, { - key: "listenClick", - value: function(e) { - var t = this; - this.listener = (0, c.default)(e, "click", function(e) { - return t.onClick(e) - }) - } - }, { - key: "onClick", - value: function(e) { - var t = e.delegateTarget || e.currentTarget; - this.clipboardAction && (this.clipboardAction = null), this.clipboardAction = new a.default({ - action: this.action(t), - target: this.target(t), - text: this.text(t), - container: this.container, - trigger: t, - emitter: this - }) - } - }, { - key: "defaultAction", - value: function(e) { - return u("action", e) - } - }, { - key: "defaultTarget", - value: function(e) { - var t = u("target", e); - if (t) return document.querySelector(t) - } - }, { - key: "defaultText", - value: function(e) { - return u("text", e) - } - }, { - key: "destroy", - value: function() { - this.listener.destroy(), this.clipboardAction && (this.clipboardAction.destroy(), this.clipboardAction = null) - } - }], [{ - key: "isSupported", - value: function() { - var e = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : ["copy", "cut"], - t = "string" == typeof e ? [e] : e, - n = !!document.queryCommandSupported; - return t.forEach(function(e) { - n = n && !!document.queryCommandSupported(e) - }), n - } - }]), r - }(); - - function u(e, t) { - var n = "data-clipboard-" + e; - if (t.hasAttribute(n)) return t.getAttribute(n) - } - e.exports = l - }, function(e, t, n) { - "use strict"; - var r, i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(e) { - return typeof e - } : function(e) { - return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e - }, - o = function() { - function r(e, t) { - for (var n = 0; n < t.length; n++) { - var r = t[n]; - r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r) - } - } - return function(e, t, n) { - return t && r(e.prototype, t), n && r(e, n), e - } - }(), - a = n(2), - s = (r = a) && r.__esModule ? r : { - default: r - }; - var c = function() { - function t(e) { - ! function(e, t) { - if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function") - }(this, t), this.resolveOptions(e), this.initSelection() - } - return o(t, [{ - key: "resolveOptions", - value: function() { - var e = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}; - this.action = e.action, this.container = e.container, this.emitter = e.emitter, this.target = e.target, this.text = e.text, this.trigger = e.trigger, this.selectedText = "" - } - }, { - key: "initSelection", - value: function() { - this.text ? this.selectFake() : this.target && this.selectTarget() - } - }, { - key: "selectFake", - value: function() { - var e = this, - t = "rtl" == document.documentElement.getAttribute("dir"); - this.removeFake(), this.fakeHandlerCallback = function() { - return e.removeFake() - }, this.fakeHandler = this.container.addEventListener("click", this.fakeHandlerCallback) || !0, this.fakeElem = document.createElement("textarea"), this.fakeElem.style.fontSize = "12pt", this.fakeElem.style.border = "0", this.fakeElem.style.padding = "0", this.fakeElem.style.margin = "0", this.fakeElem.style.position = "absolute", this.fakeElem.style[t ? "right" : "left"] = "-9999px"; - var n = window.pageYOffset || document.documentElement.scrollTop; - this.fakeElem.style.top = n + "px", this.fakeElem.setAttribute("readonly", ""), this.fakeElem.value = this.text, this.container.appendChild(this.fakeElem), this.selectedText = (0, s.default)(this.fakeElem), this.copyText() - } - }, { - key: "removeFake", - value: function() { - this.fakeHandler && (this.container.removeEventListener("click", this.fakeHandlerCallback), this.fakeHandler = null, this.fakeHandlerCallback = null), this.fakeElem && (this.container.removeChild(this.fakeElem), this.fakeElem = null) - } - }, { - key: "selectTarget", - value: function() { - this.selectedText = (0, s.default)(this.target), this.copyText() - } - }, { - key: "copyText", - value: function() { - var t = void 0; - try { - t = document.execCommand(this.action) - } catch (e) { - t = !1 - } - this.handleResult(t) - } - }, { - key: "handleResult", - value: function(e) { - this.emitter.emit(e ? "success" : "error", { - action: this.action, - text: this.selectedText, - trigger: this.trigger, - clearSelection: this.clearSelection.bind(this) - }) - } - }, { - key: "clearSelection", - value: function() { - this.trigger && this.trigger.focus(), window.getSelection().removeAllRanges() - } - }, { - key: "destroy", - value: function() { - this.removeFake() - } - }, { - key: "action", - set: function() { - var e = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : "copy"; - if (this._action = e, "copy" !== this._action && "cut" !== this._action) throw new Error('Invalid "action" value, use either "copy" or "cut"') - }, - get: function() { - return this._action - } - }, { - key: "target", - set: function(e) { - if (void 0 !== e) { - if (!e || "object" !== (void 0 === e ? "undefined" : i(e)) || 1 !== e.nodeType) throw new Error('Invalid "target" value, use a valid Element'); - if ("copy" === this.action && e.hasAttribute("disabled")) throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); - if ("cut" === this.action && (e.hasAttribute("readonly") || e.hasAttribute("disabled"))) throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); - this._target = e - } - }, - get: function() { - return this._target - } - }]), t - }(); - e.exports = c - }, function(e, t) { - e.exports = function(e) { - var t; - if ("SELECT" === e.nodeName) e.focus(), t = e.value; - else if ("INPUT" === e.nodeName || "TEXTAREA" === e.nodeName) { - var n = e.hasAttribute("readonly"); - n || e.setAttribute("readonly", ""), e.select(), e.setSelectionRange(0, e.value.length), n || e.removeAttribute("readonly"), t = e.value - } else { - e.hasAttribute("contenteditable") && e.focus(); - var r = window.getSelection(), - i = document.createRange(); - i.selectNodeContents(e), r.removeAllRanges(), r.addRange(i), t = r.toString() - } - return t - } - }, function(e, t) { - function n() {} - n.prototype = { - on: function(e, t, n) { - var r = this.e || (this.e = {}); - return (r[e] || (r[e] = [])).push({ - fn: t, - ctx: n - }), this - }, - once: function(e, t, n) { - var r = this; - - function i() { - r.off(e, i), t.apply(n, arguments) - } - return i._ = t, this.on(e, i, n) - }, - emit: function(e) { - for (var t = [].slice.call(arguments, 1), n = ((this.e || (this.e = {}))[e] || []).slice(), r = 0, i = n.length; r < i; r++) n[r].fn.apply(n[r].ctx, t); - return this - }, - off: function(e, t) { - var n = this.e || (this.e = {}), - r = n[e], - i = []; - if (r && t) - for (var o = 0, a = r.length; o < a; o++) r[o].fn !== t && r[o].fn._ !== t && i.push(r[o]); - return i.length ? n[e] = i : delete n[e], this - } - }, e.exports = n - }, function(e, t, n) { - var d = n(5), - h = n(6); - e.exports = function(e, t, n) { - if (!e && !t && !n) throw new Error("Missing required arguments"); - if (!d.string(t)) throw new TypeError("Second argument must be a String"); - if (!d.fn(n)) throw new TypeError("Third argument must be a Function"); - if (d.node(e)) return u = t, f = n, (l = e).addEventListener(u, f), { - destroy: function() { - l.removeEventListener(u, f) - } - }; - if (d.nodeList(e)) return a = e, s = t, c = n, Array.prototype.forEach.call(a, function(e) { - e.addEventListener(s, c) - }), { - destroy: function() { - Array.prototype.forEach.call(a, function(e) { - e.removeEventListener(s, c) - }) - } - }; - if (d.string(e)) return r = e, i = t, o = n, h(document.body, r, i, o); - throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList"); - var r, i, o, a, s, c, l, u, f - } - }, function(e, n) { - n.node = function(e) { - return void 0 !== e && e instanceof HTMLElement && 1 === e.nodeType - }, n.nodeList = function(e) { - var t = Object.prototype.toString.call(e); - return void 0 !== e && ("[object NodeList]" === t || "[object HTMLCollection]" === t) && "length" in e && (0 === e.length || n.node(e[0])) - }, n.string = function(e) { - return "string" == typeof e || e instanceof String - }, n.fn = function(e) { - return "[object Function]" === Object.prototype.toString.call(e) - } - }, function(e, t, n) { - var a = n(7); - - function o(e, t, n, r, i) { - var o = function(t, n, e, r) { - return function(e) { - e.delegateTarget = a(e.target, n), e.delegateTarget && r.call(t, e) - } - }.apply(this, arguments); - return e.addEventListener(n, o, i), { - destroy: function() { - e.removeEventListener(n, o, i) - } - } - } - e.exports = function(e, t, n, r, i) { - return "function" == typeof e.addEventListener ? o.apply(null, arguments) : "function" == typeof n ? o.bind(null, document).apply(null, arguments) : ("string" == typeof e && (e = document.querySelectorAll(e)), Array.prototype.map.call(e, function(e) { - return o(e, t, n, r, i) - })) - } - }, function(e, t) { - if ("undefined" != typeof Element && !Element.prototype.matches) { - var n = Element.prototype; - n.matches = n.matchesSelector || n.mozMatchesSelector || n.msMatchesSelector || n.oMatchesSelector || n.webkitMatchesSelector - } - e.exports = function(e, t) { - for (; e && 9 !== e.nodeType;) { - if ("function" == typeof e.matches && e.matches(t)) return e; - e = e.parentNode - } - } - }]) - }, e.exports = r() -}, function(r, i, o) { - var a, s; - ! function(e) { - if (void 0 === (s = "function" == typeof(a = e) ? a.call(i, o, i, r) : a) || (r.exports = s), !0, r.exports = e(), !!0) { - var t = window.Cookies, - n = window.Cookies = e(); - n.noConflict = function() { - return window.Cookies = t, n - } - } - }(function() { - function m() { - for (var e = 0, t = {}; e < arguments.length; e++) { - var n = arguments[e]; - for (var r in n) t[r] = n[r] - } - return t - } - return function e(h) { - function p(e, t, n) { - var r; - if ("undefined" != typeof document) { - if (1 < arguments.length) { - if ("number" == typeof(n = m({ - path: "/" - }, p.defaults, n)).expires) { - var i = new Date; - i.setMilliseconds(i.getMilliseconds() + 864e5 * n.expires), n.expires = i - } - n.expires = n.expires ? n.expires.toUTCString() : ""; - try { - r = JSON.stringify(t), /^[\{\[]/.test(r) && (t = r) - } catch (e) {} - t = h.write ? h.write(t, e) : encodeURIComponent(String(t)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent), e = (e = (e = encodeURIComponent(String(e))).replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)).replace(/[\(\)]/g, escape); - var o = ""; - for (var a in n) n[a] && (o += "; " + a, !0 !== n[a] && (o += "=" + n[a])); - return document.cookie = e + "=" + t + o - } - e || (r = {}); - for (var s = document.cookie ? document.cookie.split("; ") : [], c = /(%[0-9A-Z]{2})+/g, l = 0; l < s.length; l++) { - var u = s[l].split("="), - f = u.slice(1).join("="); - this.json || '"' !== f.charAt(0) || (f = f.slice(1, -1)); - try { - var d = u[0].replace(c, decodeURIComponent); - if (f = h.read ? h.read(f, d) : h(f, d) || f.replace(c, decodeURIComponent), this.json) try { - f = JSON.parse(f) - } catch (e) {} - if (e === d) { - r = f; - break - } - e || (r[d] = f) - } catch (e) {} - } - return r - } - } - return (p.set = p).get = function(e) { - return p.call(p, e) - }, p.getJSON = function() { - return p.apply({ - json: !0 - }, [].slice.call(arguments)) - }, p.defaults = {}, p.remove = function(e, t) { - p(e, "", m(t, { - expires: -1 - })) - }, p.withConverter = e, p - }(function() {}) - }) -}, function(e, t, n) { - "use strict"; - n.r(t); - var r = "function" == typeof fetch ? fetch.bind() : function(i, o) { - return o = o || {}, new Promise(function(e, t) { - var n = new XMLHttpRequest; - for (var r in n.open(o.method || "get", i, !0), o.headers) n.setRequestHeader(r, o.headers[r]); - - function s() { - var r, i = [], - o = [], - a = {}; - return n.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, function(e, t, n) { - i.push(t = t.toLowerCase()), o.push([t, n]), r = a[t], a[t] = r ? r + "," + n : n - }), { - ok: 2 == (n.status / 100 | 0), - status: n.status, - statusText: n.statusText, - url: n.responseURL, - clone: s, - text: function() { - return Promise.resolve(n.responseText) - }, - json: function() { - return Promise.resolve(n.responseText).then(JSON.parse) - }, - blob: function() { - return Promise.resolve(new Blob([n.response])) - }, - headers: { - keys: function() { - return i - }, - entries: function() { - return o - }, - get: function(e) { - return a[e.toLowerCase()] - }, - has: function(e) { - return e.toLowerCase() in a - } - } - } - } - n.withCredentials = "include" == o.credentials, n.onload = function() { - e(s()) - }, n.onerror = t, n.send(o.body || null) - }) - }; - t.default = r -}, function(e, t, n) { - "use strict"; - t.a = function(t) { - var n = this.constructor; - return this.then(function(e) { - return n.resolve(t()).then(function() { - return e - }) - }, function(e) { - return n.resolve(t()).then(function() { - return n.reject(e) - }) - }) - } -}, function(e, n, r) { - "use strict"; - (function(f) { - r.d(n, "a", function() { - return t - }); - var e = r(1), - d = r.n(e), - h = function(e) { - var t = document.getElementsByName("lang:" + e)[0]; - if (!(t instanceof HTMLMetaElement)) throw new ReferenceError; - return t.content - }, - t = function() { - function e(e, t) { - var n = "string" == typeof e ? document.querySelector(e) : e; - if (!(n instanceof HTMLElement)) throw new ReferenceError; - this.el_ = n; - var r = Array.prototype.slice.call(this.el_.children), - i = r[0], - o = r[1]; - this.data_ = t, this.meta_ = i, this.list_ = o, this.message_ = { - placeholder: this.meta_.textContent, - none: h("search.result.none"), - one: h("search.result.one"), - other: h("search.result.other") - }; - var a = h("search.tokenizer"); - a.length && (d.a.tokenizer.separator = a), this.lang_ = h("search.language").split(",").filter(Boolean).map(function(e) { - return e.trim() - }) - } - return e.prototype.update = function(e) { - var t, a = this; - if ("focus" !== e.type || this.index_) { - if ("focus" === e.type || "keyup" === e.type) { - var n = e.target; - if (!(n instanceof HTMLInputElement)) throw new ReferenceError; - if (!this.index_ || n.value === this.value_) return; - for (; this.list_.firstChild;) this.list_.removeChild(this.list_.firstChild); - if (this.value_ = n.value, 0 === this.value_.length) return void(this.meta_.textContent = this.message_.placeholder); - var r = this.index_.query(function(t) { - a.value_.toLowerCase().split(" ").filter(Boolean).forEach(function(e) { - t.term(e, { - wildcard: d.a.Query.wildcard.TRAILING - }) - }) - }).reduce(function(e, t) { - var n = a.docs_.get(t.ref); - if (n.parent) { - var r = n.parent.location; - e.set(r, (e.get(r) || []).concat(t)) - } else { - var i = n.location; - e.set(i, e.get(i) || []) - } - return e - }, new Map), - i = (t = this.value_.trim(), t.replace(/[|\\{}()[\]^$+*?.-]/g, "\\$&")).replace(new RegExp(d.a.tokenizer.separator, "img"), "|"), - s = new RegExp("(^|" + d.a.tokenizer.separator + ")(" + i + ")", "img"), - c = function(e, t, n) { - return t + "" + n + "" - }; - this.stack_ = [], r.forEach(function(e, t) { - var n, r = a.docs_.get(t), - i = f.createElement("li", { - class: "md-search-result__item" - }, f.createElement("a", { - href: r.location, - title: r.title, - class: "md-search-result__link", - tabindex: "-1" - }, f.createElement("article", { - class: "md-search-result__article md-search-result__article--document" - }, f.createElement("h1", { - class: "md-search-result__title" - }, { - __html: r.title.replace(s, c) - }), r.text.length ? f.createElement("p", { - class: "md-search-result__teaser" - }, { - __html: r.text.replace(s, c) - }) : {}))), - o = e.map(function(t) { - return function() { - var e = a.docs_.get(t.ref); - i.appendChild(f.createElement("a", { - href: e.location, - title: e.title, - class: "md-search-result__link", - "data-md-rel": "anchor", - tabindex: "-1" - }, f.createElement("article", { - class: "md-search-result__article" - }, f.createElement("h1", { - class: "md-search-result__title" - }, { - __html: e.title.replace(s, c) - }), e.text.length ? f.createElement("p", { - class: "md-search-result__teaser" - }, { - __html: function(e, t) { - var n = t; - if (e.length > n) { - for (; - " " !== e[n] && 0 < --n;); - return e.substring(0, n) + "..." - } - return e - }(e.text.replace(s, c), 400) - }) : {}))) - } - }); - (n = a.stack_).push.apply(n, [function() { - return a.list_.appendChild(i) - }].concat(o)) - }); - var o = this.el_.parentNode; - if (!(o instanceof HTMLElement)) throw new ReferenceError; - for (; this.stack_.length && o.offsetHeight >= o.scrollHeight - 16;) this.stack_.shift()(); - var l = this.list_.querySelectorAll("[data-md-rel=anchor]"); - switch (Array.prototype.forEach.call(l, function(r) { - ["click", "keydown"].forEach(function(n) { - r.addEventListener(n, function(e) { - if ("keydown" !== n || 13 === e.keyCode) { - var t = document.querySelector("[data-md-toggle=search]"); - if (!(t instanceof HTMLInputElement)) throw new ReferenceError; - t.checked && (t.checked = !1, t.dispatchEvent(new CustomEvent("change"))), e.preventDefault(), setTimeout(function() { - document.location.href = r.href - }, 100) - } - }) - }) - }), r.size) { - case 0: - this.meta_.textContent = this.message_.none; - break; - case 1: - this.meta_.textContent = this.message_.one; - break; - default: - this.meta_.textContent = this.message_.other.replace("#", r.size) - } - } - } else { - var u = function(e) { - a.docs_ = e.reduce(function(e, t) { - var n, r, i, o = t.location.split("#"), - a = o[0], - s = o[1]; - return t.text = (n = t.text, r = document.createTextNode(n), (i = document.createElement("p")).appendChild(r), i.innerHTML), s && (t.parent = e.get(a), t.parent && !t.parent.done && (t.parent.title = t.title, t.parent.text = t.text, t.parent.done = !0)), t.text = t.text.replace(/\n/g, " ").replace(/\s+/g, " ").replace(/\s+([,.:;!?])/g, function(e, t) { - return t - }), t.parent && t.parent.title === t.title || e.set(t.location, t), e - }, new Map); - var i = a.docs_, - o = a.lang_; - a.stack_ = [], a.index_ = d()(function() { - var e, t = this, - n = { - "search.pipeline.trimmer": d.a.trimmer, - "search.pipeline.stopwords": d.a.stopWordFilter - }, - r = Object.keys(n).reduce(function(e, t) { - return h(t).match(/^false$/i) || e.push(n[t]), e - }, []); - this.pipeline.reset(), r && (e = this.pipeline).add.apply(e, r), 1 === o.length && "en" !== o[0] && d.a[o[0]] ? this.use(d.a[o[0]]) : 1 < o.length && this.use(d.a.multiLanguage.apply(d.a, o)), this.field("title", { - boost: 10 - }), this.field("text"), this.ref("location"), i.forEach(function(e) { - return t.add(e) - }) - }); - var t = a.el_.parentNode; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - t.addEventListener("scroll", function() { - for (; a.stack_.length && t.scrollTop + t.offsetHeight >= t.scrollHeight - 16;) a.stack_.splice(0, 10).forEach(function(e) { - return e() - }) - }) - }; - setTimeout(function() { - return "function" == typeof a.data_ ? a.data_().then(u) : u(a.data_) - }, 250) - } - }, e - }() - }).call(this, r(3)) -}, function(e, n, r) { - "use strict"; - (function(t) { - r.d(n, "a", function() { - return e - }); - var e = function() { - function e(e) { - var t = "string" == typeof e ? document.querySelector(e) : e; - if (!(t instanceof HTMLElement)) throw new ReferenceError; - this.el_ = t - } - return e.prototype.initialize = function(e) { - e.length && this.el_.children.length && this.el_.children[this.el_.children.length - 1].appendChild(t.createElement("ul", { - class: "md-source__facts" - }, e.map(function(e) { - return t.createElement("li", { - class: "md-source__fact" - }, e) - }))), this.el_.dataset.mdState = "done" - }, e - }() - }).call(this, r(3)) -}, , , function(e, n, c) { - "use strict"; - c.r(n), - function(o) { - c.d(n, "app", function() { - return t - }); - c(14), c(15), c(16), c(17), c(18), c(19), c(20); - var r = c(2), - e = c(5), - a = c.n(e), - i = c(0); - window.Promise = window.Promise || r.a; - var s = function(e) { - var t = document.getElementsByName("lang:" + e)[0]; - if (!(t instanceof HTMLMetaElement)) throw new ReferenceError; - return t.content - }; - var t = { - initialize: function(t) { - new i.a.Event.Listener(document, "DOMContentLoaded", function() { - if (!(document.body instanceof HTMLElement)) throw new ReferenceError; - Modernizr.addTest("ios", function() { - return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g) - }); - var e = document.querySelectorAll("table:not([class])"); - if (Array.prototype.forEach.call(e, function(e) { - var t = o.createElement("div", { - class: "md-typeset__scrollwrap" - }, o.createElement("div", { - class: "md-typeset__table" - })); - e.nextSibling ? e.parentNode.insertBefore(t, e.nextSibling) : e.parentNode.appendChild(t), t.children[0].appendChild(e) - }), a.a.isSupported()) { - var t = document.querySelectorAll(".codehilite > pre, pre > code"); - Array.prototype.forEach.call(t, function(e, t) { - var n = "__code_" + t, - r = o.createElement("button", { - class: "md-clipboard", - title: s("clipboard.copy"), - "data-clipboard-target": "#" + n + " pre, #" + n + " code" - }, o.createElement("span", { - class: "md-clipboard__message" - })), - i = e.parentNode; - i.id = n, i.insertBefore(r, e) - }), new a.a(".md-clipboard").on("success", function(e) { - var t = e.trigger.querySelector(".md-clipboard__message"); - if (!(t instanceof HTMLElement)) throw new ReferenceError; - e.clearSelection(), t.dataset.mdTimer && clearTimeout(parseInt(t.dataset.mdTimer, 10)), t.classList.add("md-clipboard__message--active"), t.innerHTML = s("clipboard.copied"), t.dataset.mdTimer = setTimeout(function() { - t.classList.remove("md-clipboard__message--active"), t.dataset.mdTimer = "" - }, 2e3).toString() - }) - } - if (!Modernizr.details) { - var n = document.querySelectorAll("details > summary"); - Array.prototype.forEach.call(n, function(e) { - e.addEventListener("click", function(e) { - var t = e.target.parentNode; - t.hasAttribute("open") ? t.removeAttribute("open") : t.setAttribute("open", "") - }) - }) - } - var r = function() { - if (document.location.hash) { - var e = document.getElementById(document.location.hash.substring(1)); - if (!e) return; - for (var t = e.parentNode; t && !(t instanceof HTMLDetailsElement);) t = t.parentNode; - if (t && !t.open) { - t.open = !0; - var n = location.hash; - location.hash = " ", location.hash = n - } - } - }; - if (window.addEventListener("hashchange", r), r(), Modernizr.ios) { - var i = document.querySelectorAll("[data-md-scrollfix]"); - Array.prototype.forEach.call(i, function(t) { - t.addEventListener("touchstart", function() { - var e = t.scrollTop; - 0 === e ? t.scrollTop = 1 : e + t.offsetHeight === t.scrollHeight && (t.scrollTop = e - 1) - }) - }) - } - }).listen(), new i.a.Event.Listener(window, ["scroll", "resize", "orientationchange"], new i.a.Header.Shadow("[data-md-component=container]", "[data-md-component=header]")).listen(), new i.a.Event.Listener(window, ["scroll", "resize", "orientationchange"], new i.a.Header.Title("[data-md-component=title]", ".md-typeset h1")).listen(), document.querySelector("[data-md-component=hero]") && new i.a.Event.Listener(window, ["scroll", "resize", "orientationchange"], new i.a.Tabs.Toggle("[data-md-component=hero]")).listen(), document.querySelector("[data-md-component=tabs]") && new i.a.Event.Listener(window, ["scroll", "resize", "orientationchange"], new i.a.Tabs.Toggle("[data-md-component=tabs]")).listen(), new i.a.Event.MatchMedia("(min-width: 1220px)", new i.a.Event.Listener(window, ["scroll", "resize", "orientationchange"], new i.a.Sidebar.Position("[data-md-component=navigation]", "[data-md-component=header]"))), document.querySelector("[data-md-component=toc]") && new i.a.Event.MatchMedia("(min-width: 960px)", new i.a.Event.Listener(window, ["scroll", "resize", "orientationchange"], new i.a.Sidebar.Position("[data-md-component=toc]", "[data-md-component=header]"))), new i.a.Event.MatchMedia("(min-width: 960px)", new i.a.Event.Listener(window, "scroll", new i.a.Nav.Blur("[data-md-component=toc] .md-nav__link"))); - var e = document.querySelectorAll("[data-md-component=collapsible]"); - Array.prototype.forEach.call(e, function(e) { - new i.a.Event.MatchMedia("(min-width: 1220px)", new i.a.Event.Listener(e.previousElementSibling, "click", new i.a.Nav.Collapse(e))) - }), new i.a.Event.MatchMedia("(max-width: 1219px)", new i.a.Event.Listener("[data-md-component=navigation] [data-md-toggle]", "change", new i.a.Nav.Scrolling("[data-md-component=navigation] nav"))), document.querySelector("[data-md-component=search]") && (new i.a.Event.MatchMedia("(max-width: 959px)", new i.a.Event.Listener("[data-md-toggle=search]", "change", new i.a.Search.Lock("[data-md-toggle=search]")))), - new i.a.Event.Listener(document.body, "keydown", function(e) { - if (9 === e.keyCode) { - var t = document.querySelectorAll("[data-md-component=navigation] .md-nav__link[for]:not([tabindex])"); - Array.prototype.forEach.call(t, function(e) { - e.offsetHeight && (e.tabIndex = 0) - }) - } - }).listen(), new i.a.Event.Listener(document.body, "mousedown", function() { - var e = document.querySelectorAll("[data-md-component=navigation] .md-nav__link[tabindex]"); - Array.prototype.forEach.call(e, function(e) { - e.removeAttribute("tabIndex") - }) - }).listen(), document.body.addEventListener("click", function() { - "tabbing" === document.body.dataset.mdState && (document.body.dataset.mdState = "") - }), new i.a.Event.MatchMedia("(max-width: 959px)", new i.a.Event.Listener("[data-md-component=navigation] [href^='#']", "click", function() { - var e = document.querySelector("[data-md-toggle=drawer]"); - if (!(e instanceof HTMLInputElement)) throw new ReferenceError; - e.checked && (e.checked = !1, e.dispatchEvent(new CustomEvent("change"))) - })), - function() { - var e = document.querySelector("[data-md-source]"); - if (!e) return r.a.resolve([]); - if (!(e instanceof HTMLAnchorElement)) throw new ReferenceError; - switch (e.dataset.mdSource) { - case "github": - return new i.a.Source.Adapter.GitHub(e).fetch(); - default: - return r.a.resolve([]) - } - }().then(function(t) { - var e = document.querySelectorAll("[data-md-source]"); - Array.prototype.forEach.call(e, function(e) { - new i.a.Source.Repository(e).initialize(t) - }) - }); - var n = function() { - var e = document.querySelectorAll("details"); - Array.prototype.forEach.call(e, function(e) { - e.setAttribute("open", "") - }) - }; - new i.a.Event.MatchMedia("print", { - listen: n, - unlisten: function() {} - }), window.onbeforeprint = n - } - } - }.call(this, c(3)) -}, function(e, t, n) { - e.exports = n.p + "assets/images/icons/bitbucket.1b09e088.svg" -}, function(e, t, n) { - e.exports = n.p + "assets/images/icons/github.f0b8504a.svg" -}, function(e, t, n) { - e.exports = n.p + "assets/images/icons/gitlab.6dd19c00.svg" -}, function(e, t) { - e.exports = "/Users/squidfunk/Desktop/General/Sources/mkdocs-material/material/application.4031d38b.css" -}, function(e, t) { - e.exports = "/Users/squidfunk/Desktop/General/Sources/mkdocs-material/material/application-palette.224b79ff.css" -}, function(e, t) { - ! function() { - if ("undefined" != typeof window) try { - var e = new window.CustomEvent("test", { - cancelable: !0 - }); - if (e.preventDefault(), !0 !== e.defaultPrevented) throw new Error("Could not prevent default") - } catch (e) { - var t = function(e, t) { - var n, r; - return (t = t || {}).bubbles = !!t.bubbles, t.cancelable = !!t.cancelable, (n = document.createEvent("CustomEvent")).initCustomEvent(e, t.bubbles, t.cancelable, t.detail), r = n.preventDefault, n.preventDefault = function() { - r.call(this); - try { - Object.defineProperty(this, "defaultPrevented", { - get: function() { - return !0 - } - }) - } catch (e) { - this.defaultPrevented = !0 - } - }, n - }; - t.prototype = window.Event.prototype, window.CustomEvent = t - } - }() -}, function(e, t, n) { - window.fetch || (window.fetch = n(7).default || n(7)) -}, function(e, i, o) { - (function(e) { - var t = void 0 !== e && e || "undefined" != typeof self && self || window, - n = Function.prototype.apply; - - function r(e, t) { - this._id = e, this._clearFn = t - } - i.setTimeout = function() { - return new r(n.call(setTimeout, t, arguments), clearTimeout) - }, i.setInterval = function() { - return new r(n.call(setInterval, t, arguments), clearInterval) - }, i.clearTimeout = i.clearInterval = function(e) { - e && e.close() - }, r.prototype.unref = r.prototype.ref = function() {}, r.prototype.close = function() { - this._clearFn.call(t, this._id) - }, i.enroll = function(e, t) { - clearTimeout(e._idleTimeoutId), e._idleTimeout = t - }, i.unenroll = function(e) { - clearTimeout(e._idleTimeoutId), e._idleTimeout = -1 - }, i._unrefActive = i.active = function(e) { - clearTimeout(e._idleTimeoutId); - var t = e._idleTimeout; - 0 <= t && (e._idleTimeoutId = setTimeout(function() { - e._onTimeout && e._onTimeout() - }, t)) - }, o(22), i.setImmediate = "undefined" != typeof self && self.setImmediate || void 0 !== e && e.setImmediate || this && this.setImmediate, i.clearImmediate = "undefined" != typeof self && self.clearImmediate || void 0 !== e && e.clearImmediate || this && this.clearImmediate - }).call(this, o(4)) -}, function(e, t, n) { - (function(e, p) { - ! function(n, r) { - "use strict"; - if (!n.setImmediate) { - var i, o, t, a, e, s = 1, - c = {}, - l = !1, - u = n.document, - f = Object.getPrototypeOf && Object.getPrototypeOf(n); - f = f && f.setTimeout ? f : n, i = "[object process]" === {}.toString.call(n.process) ? function(e) { - p.nextTick(function() { - h(e) - }) - } : function() { - if (n.postMessage && !n.importScripts) { - var e = !0, - t = n.onmessage; - return n.onmessage = function() { - e = !1 - }, n.postMessage("", "*"), n.onmessage = t, e - } - }() ? (a = "setImmediate$" + Math.random() + "$", e = function(e) { - e.source === n && "string" == typeof e.data && 0 === e.data.indexOf(a) && h(+e.data.slice(a.length)) - }, n.addEventListener ? n.addEventListener("message", e, !1) : n.attachEvent("onmessage", e), function(e) { - n.postMessage(a + e, "*") - }) : n.MessageChannel ? ((t = new MessageChannel).port1.onmessage = function(e) { - h(e.data) - }, function(e) { - t.port2.postMessage(e) - }) : u && "onreadystatechange" in u.createElement("script") ? (o = u.documentElement, function(e) { - var t = u.createElement("script"); - t.onreadystatechange = function() { - h(e), t.onreadystatechange = null, o.removeChild(t), t = null - }, o.appendChild(t) - }) : function(e) { - setTimeout(h, 0, e) - }, f.setImmediate = function(e) { - "function" != typeof e && (e = new Function("" + e)); - for (var t = new Array(arguments.length - 1), n = 0; n < t.length; n++) t[n] = arguments[n + 1]; - var r = { - callback: e, - args: t - }; - return c[s] = r, i(s), s++ - }, f.clearImmediate = d - } - - function d(e) { - delete c[e] - } - - function h(e) { - if (l) setTimeout(h, 0, e); - else { - var t = c[e]; - if (t) { - l = !0; - try { - ! function(e) { - var t = e.callback, - n = e.args; - switch (n.length) { - case 0: - t(); - break; - case 1: - t(n[0]); - break; - case 2: - t(n[0], n[1]); - break; - case 3: - t(n[0], n[1], n[2]); - break; - default: - t.apply(r, n) - } - }(t) - } finally { - d(e), l = !1 - } - } - } - } - }("undefined" == typeof self ? void 0 === e ? this : e : self) - }).call(this, n(4), n(23)) -}, function(e, t) { - var n, r, i = e.exports = {}; - - function o() { - throw new Error("setTimeout has not been defined") - } - - function a() { - throw new Error("clearTimeout has not been defined") - } - - function s(t) { - if (n === setTimeout) return setTimeout(t, 0); - if ((n === o || !n) && setTimeout) return n = setTimeout, setTimeout(t, 0); - try { - return n(t, 0) - } catch (e) { - try { - return n.call(null, t, 0) - } catch (e) { - return n.call(this, t, 0) - } - } - }! function() { - try { - n = "function" == typeof setTimeout ? setTimeout : o - } catch (e) { - n = o - } - try { - r = "function" == typeof clearTimeout ? clearTimeout : a - } catch (e) { - r = a - } - }(); - var c, l = [], - u = !1, - f = -1; - - function d() { - u && c && (u = !1, c.length ? l = c.concat(l) : f = -1, l.length && h()) - } - - function h() { - if (!u) { - var e = s(d); - u = !0; - for (var t = l.length; t;) { - for (c = l, l = []; ++f < t;) c && c[f].run(); - f = -1, t = l.length - } - c = null, u = !1, - function(t) { - if (r === clearTimeout) return clearTimeout(t); - if ((r === a || !r) && clearTimeout) return r = clearTimeout, clearTimeout(t); - try { - r(t) - } catch (e) { - try { - return r.call(null, t) - } catch (e) { - return r.call(this, t) - } - } - }(e) - } - } - - function p(e, t) { - this.fun = e, this.array = t - } - - function m() {} - i.nextTick = function(e) { - var t = new Array(arguments.length - 1); - if (1 < arguments.length) - for (var n = 1; n < arguments.length; n++) t[n - 1] = arguments[n]; - l.push(new p(e, t)), 1 !== l.length || u || s(h) - }, p.prototype.run = function() { - this.fun.apply(null, this.array) - }, i.title = "browser", i.browser = !0, i.env = {}, i.argv = [], i.version = "", i.versions = {}, i.on = m, i.addListener = m, i.once = m, i.off = m, i.removeListener = m, i.removeAllListeners = m, i.emit = m, i.prependListener = m, i.prependOnceListener = m, i.listeners = function(e) { - return [] - }, i.binding = function(e) { - throw new Error("process.binding is not supported") - }, i.cwd = function() { - return "/" - }, i.chdir = function(e) { - throw new Error("process.chdir is not supported") - }, i.umask = function() { - return 0 - } -}, function(i, o, a) { - var s, c; - /** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.6 - * Copyright (C) 2019 Oliver Nightingale - * @license MIT - */ - ! function() { - var t, l, u, e, n, f, d, h, p, m, y, v, g, w, _, E, x, b, k, S, T, L, R, O, C, r, D = function(e) { - var t = new D.Builder; - return t.pipeline.add(D.trimmer, D.stopWordFilter, D.stemmer), t.searchPipeline.add(D.stemmer), e.call(t, t), t.build() - }; - D.version = "2.3.6", D.utils = {}, D.utils.warn = (t = this, function(e) { - t.console && console.warn && console.warn(e) - }), D.utils.asString = function(e) { - return null == e ? "" : e.toString() - }, D.utils.clone = function(e) { - if (null == e) return e; - for (var t = Object.create(null), n = Object.keys(e), r = 0; r < n.length; r++) { - var i = n[r], - o = e[i]; - if (Array.isArray(o)) t[i] = o.slice(); - else { - if ("string" != typeof o && "number" != typeof o && "boolean" != typeof o) throw new TypeError("clone is not deep and does not support nested objects"); - t[i] = o - } - } - return t - }, D.FieldRef = function(e, t, n) { - this.docRef = e, this.fieldName = t, this._stringValue = n - }, D.FieldRef.joiner = "/", D.FieldRef.fromString = function(e) { - var t = e.indexOf(D.FieldRef.joiner); - if (-1 === t) throw "malformed field ref string"; - var n = e.slice(0, t), - r = e.slice(t + 1); - return new D.FieldRef(r, n, e) - }, D.FieldRef.prototype.toString = function() { - return null == this._stringValue && (this._stringValue = this.fieldName + D.FieldRef.joiner + this.docRef), this._stringValue - }, D.Set = function(e) { - if (this.elements = Object.create(null), e) { - this.length = e.length; - for (var t = 0; t < this.length; t++) this.elements[e[t]] = !0 - } else this.length = 0 - }, D.Set.complete = { - intersect: function(e) { - return e - }, - union: function(e) { - return e - }, - contains: function() { - return !0 - } - }, D.Set.empty = { - intersect: function() { - return this - }, - union: function(e) { - return e - }, - contains: function() { - return !1 - } - }, D.Set.prototype.contains = function(e) { - return !!this.elements[e] - }, D.Set.prototype.intersect = function(e) { - var t, n, r, i = []; - if (e === D.Set.complete) return this; - if (e === D.Set.empty) return e; - n = this.length < e.length ? (t = this, e) : (t = e, this), r = Object.keys(t.elements); - for (var o = 0; o < r.length; o++) { - var a = r[o]; - a in n.elements && i.push(a) - } - return new D.Set(i) - }, D.Set.prototype.union = function(e) { - return e === D.Set.complete ? D.Set.complete : e === D.Set.empty ? this : new D.Set(Object.keys(this.elements).concat(Object.keys(e.elements))) - }, D.idf = function(e, t) { - var n = 0; - for (var r in e) "_index" != r && (n += Object.keys(e[r]).length); - var i = (t - n + .5) / (n + .5); - return Math.log(1 + Math.abs(i)) - }, D.Token = function(e, t) { - this.str = e || "", this.metadata = t || {} - }, D.Token.prototype.toString = function() { - return this.str - }, D.Token.prototype.update = function(e) { - return this.str = e(this.str, this.metadata), this - }, D.Token.prototype.clone = function(e) { - return e = e || function(e) { - return e - }, new D.Token(e(this.str, this.metadata), this.metadata) - }, D.tokenizer = function(e, t) { - if (null == e || null == e) return []; - if (Array.isArray(e)) return e.map(function(e) { - return new D.Token(D.utils.asString(e).toLowerCase(), D.utils.clone(t)) - }); - for (var n = e.toString().trim().toLowerCase(), r = n.length, i = [], o = 0, a = 0; o <= r; o++) { - var s = o - a; - if (n.charAt(o).match(D.tokenizer.separator) || o == r) { - if (0 < s) { - var c = D.utils.clone(t) || {}; - c.position = [a, s], c.index = i.length, i.push(new D.Token(n.slice(a, o), c)) - } - a = o + 1 - } - } - return i - }, D.tokenizer.separator = /[\s\-]+/, D.Pipeline = function() { - this._stack = [] - }, D.Pipeline.registeredFunctions = Object.create(null), D.Pipeline.registerFunction = function(e, t) { - t in this.registeredFunctions && D.utils.warn("Overwriting existing registered function: " + t), e.label = t, D.Pipeline.registeredFunctions[e.label] = e - }, D.Pipeline.warnIfFunctionNotRegistered = function(e) { - e.label && e.label in this.registeredFunctions || D.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n", e) - }, D.Pipeline.load = function(e) { - var n = new D.Pipeline; - return e.forEach(function(e) { - var t = D.Pipeline.registeredFunctions[e]; - if (!t) throw new Error("Cannot load unregistered function: " + e); - n.add(t) - }), n - }, D.Pipeline.prototype.add = function() { - Array.prototype.slice.call(arguments).forEach(function(e) { - D.Pipeline.warnIfFunctionNotRegistered(e), this._stack.push(e) - }, this) - }, D.Pipeline.prototype.after = function(e, t) { - D.Pipeline.warnIfFunctionNotRegistered(t); - var n = this._stack.indexOf(e); - if (-1 == n) throw new Error("Cannot find existingFn"); - n += 1, this._stack.splice(n, 0, t) - }, D.Pipeline.prototype.before = function(e, t) { - D.Pipeline.warnIfFunctionNotRegistered(t); - var n = this._stack.indexOf(e); - if (-1 == n) throw new Error("Cannot find existingFn"); - this._stack.splice(n, 0, t) - }, D.Pipeline.prototype.remove = function(e) { - var t = this._stack.indexOf(e); - 1 != t && this._stack.splice(t, 1) - }, D.Pipeline.prototype.run = function(e) { - for (var t = this._stack.length, n = 0; n < t; n++) { - for (var r = this._stack[n], i = [], o = 0; o < e.length; o++) { - var a = r(e[o], o, e); - if (void 0 !== a && "" !== a) - if (Array.isArray(a)) - for (var s = 0; s < a.length; s++) i.push(a[s]); - else i.push(a) - } - e = i - } - return e - }, D.Pipeline.prototype.runString = function(e, t) { - var n = new D.Token(e, t); - return this.run([n]).map(function(e) { - return e.toString() - }) - }, D.Pipeline.prototype.reset = function() { - this._stack = [] - }, D.Pipeline.prototype.toJSON = function() { - return this._stack.map(function(e) { - return D.Pipeline.warnIfFunctionNotRegistered(e), e.label - }) - }, D.Vector = function(e) { - this._magnitude = 0, this.elements = e || [] - }, D.Vector.prototype.positionForIndex = function(e) { - if (0 == this.elements.length) return 0; - for (var t = 0, n = this.elements.length / 2, r = n - t, i = Math.floor(r / 2), o = this.elements[2 * i]; 1 < r && (o < e && (t = i), e < o && (n = i), o != e);) r = n - t, i = t + Math.floor(r / 2), o = this.elements[2 * i]; - return o == e ? 2 * i : e < o ? 2 * i : o < e ? 2 * (i + 1) : void 0 - }, D.Vector.prototype.insert = function(e, t) { - this.upsert(e, t, function() { - throw "duplicate index" - }) - }, D.Vector.prototype.upsert = function(e, t, n) { - this._magnitude = 0; - var r = this.positionForIndex(e); - this.elements[r] == e ? this.elements[r + 1] = n(this.elements[r + 1], t) : this.elements.splice(r, 0, e, t) - }, D.Vector.prototype.magnitude = function() { - if (this._magnitude) return this._magnitude; - for (var e = 0, t = this.elements.length, n = 1; n < t; n += 2) { - var r = this.elements[n]; - e += r * r - } - return this._magnitude = Math.sqrt(e) - }, D.Vector.prototype.dot = function(e) { - for (var t = 0, n = this.elements, r = e.elements, i = n.length, o = r.length, a = 0, s = 0, c = 0, l = 0; c < i && l < o;)(a = n[c]) < (s = r[l]) ? c += 2 : s < a ? l += 2 : a == s && (t += n[c + 1] * r[l + 1], c += 2, l += 2); - return t - }, D.Vector.prototype.similarity = function(e) { - return this.dot(e) / this.magnitude() || 0 - }, D.Vector.prototype.toArray = function() { - for (var e = new Array(this.elements.length / 2), t = 1, n = 0; t < this.elements.length; t += 2, n++) e[n] = this.elements[t]; - return e - }, D.Vector.prototype.toJSON = function() { - return this.elements - }, D.stemmer = (l = { - ational: "ate", - tional: "tion", - enci: "ence", - anci: "ance", - izer: "ize", - bli: "ble", - alli: "al", - entli: "ent", - eli: "e", - ousli: "ous", - ization: "ize", - ation: "ate", - ator: "ate", - alism: "al", - iveness: "ive", - fulness: "ful", - ousness: "ous", - aliti: "al", - iviti: "ive", - biliti: "ble", - logi: "log" - }, u = { - icate: "ic", - ative: "", - alize: "al", - iciti: "ic", - ical: "ic", - ful: "", - ness: "" - }, e = "[aeiouy]", n = "[^aeiou][^aeiouy]*", f = new RegExp("^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*"), d = new RegExp("^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*[aeiouy][aeiou]*[^aeiou][^aeiouy]*"), h = new RegExp("^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*([aeiouy][aeiou]*)?$"), p = new RegExp("^([^aeiou][^aeiouy]*)?[aeiouy]"), m = /^(.+?)(ss|i)es$/, y = /^(.+?)([^s])s$/, v = /^(.+?)eed$/, g = /^(.+?)(ed|ing)$/, w = /.$/, _ = /(at|bl|iz)$/, E = new RegExp("([^aeiouylsz])\\1$"), x = new RegExp("^" + n + e + "[^aeiouwxy]$"), b = /^(.+?[^aeiou])y$/, k = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/, S = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/, T = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/, L = /^(.+?)(s|t)(ion)$/, R = /^(.+?)e$/, O = /ll$/, C = new RegExp("^" + n + e + "[^aeiouwxy]$"), r = function(e) { - var t, n, r, i, o, a, s; - if (e.length < 3) return e; - if ("y" == (r = e.substr(0, 1)) && (e = r.toUpperCase() + e.substr(1)), o = y, (i = m).test(e) ? e = e.replace(i, "$1$2") : o.test(e) && (e = e.replace(o, "$1$2")), o = g, (i = v).test(e)) { - var c = i.exec(e); - (i = f).test(c[1]) && (i = w, e = e.replace(i, "")) - } else if (o.test(e)) { - t = (c = o.exec(e))[1], (o = p).test(t) && (a = E, s = x, (o = _).test(e = t) ? e += "e" : a.test(e) ? (i = w, e = e.replace(i, "")) : s.test(e) && (e += "e")) - }(i = b).test(e) && (e = (t = (c = i.exec(e))[1]) + "i"); - (i = k).test(e) && (t = (c = i.exec(e))[1], n = c[2], (i = f).test(t) && (e = t + l[n])); - (i = S).test(e) && (t = (c = i.exec(e))[1], n = c[2], (i = f).test(t) && (e = t + u[n])); - if (o = L, (i = T).test(e)) t = (c = i.exec(e))[1], (i = d).test(t) && (e = t); - else if (o.test(e)) { - t = (c = o.exec(e))[1] + c[2], (o = d).test(t) && (e = t) - }(i = R).test(e) && (t = (c = i.exec(e))[1], o = h, a = C, ((i = d).test(t) || o.test(t) && !a.test(t)) && (e = t)); - return o = d, (i = O).test(e) && o.test(e) && (i = w, e = e.replace(i, "")), "y" == r && (e = r.toLowerCase() + e.substr(1)), e - }, function(e) { - return e.update(r) - }), D.Pipeline.registerFunction(D.stemmer, "stemmer"), D.generateStopWordFilter = function(e) { - var t = e.reduce(function(e, t) { - return e[t] = t, e - }, {}); - return function(e) { - if (e && t[e.toString()] !== e.toString()) return e - } - }, D.stopWordFilter = D.generateStopWordFilter(["a", "able", "about", "across", "after", "all", "almost", "also", "am", "among", "an", "and", "any", "are", "as", "at", "be", "because", "been", "but", "by", "can", "cannot", "could", "dear", "did", "do", "does", "either", "else", "ever", "every", "for", "from", "get", "got", "had", "has", "have", "he", "her", "hers", "him", "his", "how", "however", "i", "if", "in", "into", "is", "it", "its", "just", "least", "let", "like", "likely", "may", "me", "might", "most", "must", "my", "neither", "no", "nor", "not", "of", "off", "often", "on", "only", "or", "other", "our", "own", "rather", "said", "say", "says", "she", "should", "since", "so", "some", "than", "that", "the", "their", "them", "then", "there", "these", "they", "this", "tis", "to", "too", "twas", "us", "wants", "was", "we", "were", "what", "when", "where", "which", "while", "who", "whom", "why", "will", "with", "would", "yet", "you", "your"]), D.Pipeline.registerFunction(D.stopWordFilter, "stopWordFilter"), D.trimmer = function(e) { - return e.update(function(e) { - return e.replace(/^\W+/, "").replace(/\W+$/, "") - }) - }, D.Pipeline.registerFunction(D.trimmer, "trimmer"), D.TokenSet = function() { - this.final = !1, this.edges = {}, this.id = D.TokenSet._nextId, D.TokenSet._nextId += 1 - }, D.TokenSet._nextId = 1, D.TokenSet.fromArray = function(e) { - for (var t = new D.TokenSet.Builder, n = 0, r = e.length; n < r; n++) t.insert(e[n]); - return t.finish(), t.root - }, D.TokenSet.fromClause = function(e) { - return "editDistance" in e ? D.TokenSet.fromFuzzyString(e.term, e.editDistance) : D.TokenSet.fromString(e.term) - }, D.TokenSet.fromFuzzyString = function(e, t) { - for (var n = new D.TokenSet, r = [{ - node: n, - editsRemaining: t, - str: e - }]; r.length;) { - var i = r.pop(); - if (0 < i.str.length) { - var o, a = i.str.charAt(0); - a in i.node.edges ? o = i.node.edges[a] : (o = new D.TokenSet, i.node.edges[a] = o), 1 == i.str.length && (o.final = !0), r.push({ - node: o, - editsRemaining: i.editsRemaining, - str: i.str.slice(1) - }) - } - if (0 != i.editsRemaining) { - if ("*" in i.node.edges) var s = i.node.edges["*"]; - else { - s = new D.TokenSet; - i.node.edges["*"] = s - } - if (0 == i.str.length && (s.final = !0), r.push({ - node: s, - editsRemaining: i.editsRemaining - 1, - str: i.str - }), 1 < i.str.length && r.push({ - node: i.node, - editsRemaining: i.editsRemaining - 1, - str: i.str.slice(1) - }), 1 == i.str.length && (i.node.final = !0), 1 <= i.str.length) { - if ("*" in i.node.edges) var c = i.node.edges["*"]; - else { - c = new D.TokenSet; - i.node.edges["*"] = c - } - 1 == i.str.length && (c.final = !0), r.push({ - node: c, - editsRemaining: i.editsRemaining - 1, - str: i.str.slice(1) - }) - } - if (1 < i.str.length) { - var l, u = i.str.charAt(0), - f = i.str.charAt(1); - f in i.node.edges ? l = i.node.edges[f] : (l = new D.TokenSet, i.node.edges[f] = l), 1 == i.str.length && (l.final = !0), r.push({ - node: l, - editsRemaining: i.editsRemaining - 1, - str: u + i.str.slice(2) - }) - } - } - } - return n - }, D.TokenSet.fromString = function(e) { - for (var t = new D.TokenSet, n = t, r = 0, i = e.length; r < i; r++) { - var o = e[r], - a = r == i - 1; - if ("*" == o)(t.edges[o] = t).final = a; - else { - var s = new D.TokenSet; - s.final = a, t.edges[o] = s, t = s - } - } - return n - }, D.TokenSet.prototype.toArray = function() { - for (var e = [], t = [{ - prefix: "", - node: this - }]; t.length;) { - var n = t.pop(), - r = Object.keys(n.node.edges), - i = r.length; - n.node.final && (n.prefix.charAt(0), e.push(n.prefix)); - for (var o = 0; o < i; o++) { - var a = r[o]; - t.push({ - prefix: n.prefix.concat(a), - node: n.node.edges[a] - }) - } - } - return e - }, D.TokenSet.prototype.toString = function() { - if (this._str) return this._str; - for (var e = this.final ? "1" : "0", t = Object.keys(this.edges).sort(), n = t.length, r = 0; r < n; r++) { - var i = t[r]; - e = e + i + this.edges[i].id - } - return e - }, D.TokenSet.prototype.intersect = function(e) { - for (var t = new D.TokenSet, n = void 0, r = [{ - qNode: e, - output: t, - node: this - }]; r.length;) { - n = r.pop(); - for (var i = Object.keys(n.qNode.edges), o = i.length, a = Object.keys(n.node.edges), s = a.length, c = 0; c < o; c++) - for (var l = i[c], u = 0; u < s; u++) { - var f = a[u]; - if (f == l || "*" == l) { - var d = n.node.edges[f], - h = n.qNode.edges[l], - p = d.final && h.final, - m = void 0; - f in n.output.edges ? (m = n.output.edges[f]).final = m.final || p : ((m = new D.TokenSet).final = p, n.output.edges[f] = m), r.push({ - qNode: h, - output: m, - node: d - }) - } - } - } - return t - }, D.TokenSet.Builder = function() { - this.previousWord = "", this.root = new D.TokenSet, this.uncheckedNodes = [], this.minimizedNodes = {} - }, D.TokenSet.Builder.prototype.insert = function(e) { - var t, n = 0; - if (e < this.previousWord) throw new Error("Out of order word insertion"); - for (var r = 0; r < e.length && r < this.previousWord.length && e[r] == this.previousWord[r]; r++) n++; - this.minimize(n), t = 0 == this.uncheckedNodes.length ? this.root : this.uncheckedNodes[this.uncheckedNodes.length - 1].child; - for (r = n; r < e.length; r++) { - var i = new D.TokenSet, - o = e[r]; - t.edges[o] = i, this.uncheckedNodes.push({ - parent: t, - char: o, - child: i - }), t = i - } - t.final = !0, this.previousWord = e - }, D.TokenSet.Builder.prototype.finish = function() { - this.minimize(0) - }, D.TokenSet.Builder.prototype.minimize = function(e) { - for (var t = this.uncheckedNodes.length - 1; e <= t; t--) { - var n = this.uncheckedNodes[t], - r = n.child.toString(); - r in this.minimizedNodes ? n.parent.edges[n.char] = this.minimizedNodes[r] : (n.child._str = r, this.minimizedNodes[r] = n.child), this.uncheckedNodes.pop() - } - }, D.Index = function(e) { - this.invertedIndex = e.invertedIndex, this.fieldVectors = e.fieldVectors, this.tokenSet = e.tokenSet, this.fields = e.fields, this.pipeline = e.pipeline - }, D.Index.prototype.search = function(t) { - return this.query(function(e) { - new D.QueryParser(t, e).parse() - }) - }, D.Index.prototype.query = function(e) { - for (var t = new D.Query(this.fields), n = Object.create(null), r = Object.create(null), i = Object.create(null), o = Object.create(null), a = Object.create(null), s = 0; s < this.fields.length; s++) r[this.fields[s]] = new D.Vector; - e.call(t, t); - for (s = 0; s < t.clauses.length; s++) { - var c = t.clauses[s], - l = null, - u = D.Set.complete; - l = c.usePipeline ? this.pipeline.runString(c.term, { - fields: c.fields - }) : [c.term]; - for (var f = 0; f < l.length; f++) { - var d = l[f]; - c.term = d; - var h = D.TokenSet.fromClause(c), - p = this.tokenSet.intersect(h).toArray(); - if (0 === p.length && c.presence === D.Query.presence.REQUIRED) { - for (var m = 0; m < c.fields.length; m++) { - o[Q = c.fields[m]] = D.Set.empty - } - break - } - for (var y = 0; y < p.length; y++) { - var v = p[y], - g = this.invertedIndex[v], - w = g._index; - for (m = 0; m < c.fields.length; m++) { - var _ = g[Q = c.fields[m]], - E = Object.keys(_), - x = v + "/" + Q, - b = new D.Set(E); - if (c.presence == D.Query.presence.REQUIRED && (u = u.union(b), void 0 === o[Q] && (o[Q] = D.Set.complete)), c.presence != D.Query.presence.PROHIBITED) { - if (r[Q].upsert(w, c.boost, function(e, t) { - return e + t - }), !i[x]) { - for (var k = 0; k < E.length; k++) { - var S, T = E[k], - L = new D.FieldRef(T, Q), - R = _[T]; - void 0 === (S = n[L]) ? n[L] = new D.MatchData(v, Q, R) : S.add(v, Q, R) - } - i[x] = !0 - } - } else void 0 === a[Q] && (a[Q] = D.Set.empty), a[Q] = a[Q].union(b) - } - } - } - if (c.presence === D.Query.presence.REQUIRED) - for (m = 0; m < c.fields.length; m++) { - o[Q = c.fields[m]] = o[Q].intersect(u) - } - } - var O = D.Set.complete, - C = D.Set.empty; - for (s = 0; s < this.fields.length; s++) { - var Q; - o[Q = this.fields[s]] && (O = O.intersect(o[Q])), a[Q] && (C = C.union(a[Q])) - } - var P = Object.keys(n), - A = [], - I = Object.create(null); - if (t.isNegated()) { - P = Object.keys(this.fieldVectors); - for (s = 0; s < P.length; s++) { - L = P[s]; - var M = D.FieldRef.fromString(L); - n[L] = new D.MatchData - } - } - for (s = 0; s < P.length; s++) { - var N = (M = D.FieldRef.fromString(P[s])).docRef; - if (O.contains(N) && !C.contains(N)) { - var j, F = this.fieldVectors[M], - H = r[M.fieldName].similarity(F); - if (void 0 !== (j = I[N])) j.score += H, j.matchData.combine(n[M]); - else { - var q = { - ref: N, - score: H, - matchData: n[M] - }; - I[N] = q, A.push(q) - } - } - } - return A.sort(function(e, t) { - return t.score - e.score - }) - }, D.Index.prototype.toJSON = function() { - var e = Object.keys(this.invertedIndex).sort().map(function(e) { - return [e, this.invertedIndex[e]] - }, this), - t = Object.keys(this.fieldVectors).map(function(e) { - return [e, this.fieldVectors[e].toJSON()] - }, this); - return { - version: D.version, - fields: this.fields, - fieldVectors: t, - invertedIndex: e, - pipeline: this.pipeline.toJSON() - } - }, D.Index.load = function(e) { - var t = {}, - n = {}, - r = e.fieldVectors, - i = Object.create(null), - o = e.invertedIndex, - a = new D.TokenSet.Builder, - s = D.Pipeline.load(e.pipeline); - e.version != D.version && D.utils.warn("Version mismatch when loading serialised index. Current version of lunr '" + D.version + "' does not match serialized index '" + e.version + "'"); - for (var c = 0; c < r.length; c++) { - var l = (f = r[c])[0], - u = f[1]; - n[l] = new D.Vector(u) - } - for (c = 0; c < o.length; c++) { - var f, d = (f = o[c])[0], - h = f[1]; - a.insert(d), i[d] = h - } - return a.finish(), t.fields = e.fields, t.fieldVectors = n, t.invertedIndex = i, t.tokenSet = a.root, t.pipeline = s, new D.Index(t) - }, D.Builder = function() { - this._ref = "id", this._fields = Object.create(null), this._documents = Object.create(null), this.invertedIndex = Object.create(null), this.fieldTermFrequencies = {}, this.fieldLengths = {}, this.tokenizer = D.tokenizer, this.pipeline = new D.Pipeline, this.searchPipeline = new D.Pipeline, this.documentCount = 0, this._b = .75, this._k1 = 1.2, this.termIndex = 0, this.metadataWhitelist = [] - }, D.Builder.prototype.ref = function(e) { - this._ref = e - }, D.Builder.prototype.field = function(e, t) { - if (/\//.test(e)) throw new RangeError("Field '" + e + "' contains illegal character '/'"); - this._fields[e] = t || {} - }, D.Builder.prototype.b = function(e) { - this._b = e < 0 ? 0 : 1 < e ? 1 : e - }, D.Builder.prototype.k1 = function(e) { - this._k1 = e - }, D.Builder.prototype.add = function(e, t) { - var n = e[this._ref], - r = Object.keys(this._fields); - this._documents[n] = t || {}, this.documentCount += 1; - for (var i = 0; i < r.length; i++) { - var o = r[i], - a = this._fields[o].extractor, - s = a ? a(e) : e[o], - c = this.tokenizer(s, { - fields: [o] - }), - l = this.pipeline.run(c), - u = new D.FieldRef(n, o), - f = Object.create(null); - this.fieldTermFrequencies[u] = f, this.fieldLengths[u] = 0, this.fieldLengths[u] += l.length; - for (var d = 0; d < l.length; d++) { - var h = l[d]; - if (null == f[h] && (f[h] = 0), f[h] += 1, null == this.invertedIndex[h]) { - var p = Object.create(null); - p._index = this.termIndex, this.termIndex += 1; - for (var m = 0; m < r.length; m++) p[r[m]] = Object.create(null); - this.invertedIndex[h] = p - } - null == this.invertedIndex[h][o][n] && (this.invertedIndex[h][o][n] = Object.create(null)); - for (var y = 0; y < this.metadataWhitelist.length; y++) { - var v = this.metadataWhitelist[y], - g = h.metadata[v]; - null == this.invertedIndex[h][o][n][v] && (this.invertedIndex[h][o][n][v] = []), this.invertedIndex[h][o][n][v].push(g) - } - } - } - }, D.Builder.prototype.calculateAverageFieldLengths = function() { - for (var e = Object.keys(this.fieldLengths), t = e.length, n = {}, r = {}, i = 0; i < t; i++) { - var o = D.FieldRef.fromString(e[i]), - a = o.fieldName; - r[a] || (r[a] = 0), r[a] += 1, n[a] || (n[a] = 0), n[a] += this.fieldLengths[o] - } - var s = Object.keys(this._fields); - for (i = 0; i < s.length; i++) { - var c = s[i]; - n[c] = n[c] / r[c] - } - this.averageFieldLength = n - }, D.Builder.prototype.createFieldVectors = function() { - for (var e = {}, t = Object.keys(this.fieldTermFrequencies), n = t.length, r = Object.create(null), i = 0; i < n; i++) { - for (var o = D.FieldRef.fromString(t[i]), a = o.fieldName, s = this.fieldLengths[o], c = new D.Vector, l = this.fieldTermFrequencies[o], u = Object.keys(l), f = u.length, d = this._fields[a].boost || 1, h = this._documents[o.docRef].boost || 1, p = 0; p < f; p++) { - var m, y, v, g = u[p], - w = l[g], - _ = this.invertedIndex[g]._index; - void 0 === r[g] ? (m = D.idf(this.invertedIndex[g], this.documentCount), r[g] = m) : m = r[g], y = m * ((this._k1 + 1) * w) / (this._k1 * (1 - this._b + this._b * (s / this.averageFieldLength[a])) + w), y *= d, y *= h, v = Math.round(1e3 * y) / 1e3, c.insert(_, v) - } - e[o] = c - } - this.fieldVectors = e - }, D.Builder.prototype.createTokenSet = function() { - this.tokenSet = D.TokenSet.fromArray(Object.keys(this.invertedIndex).sort()) - }, D.Builder.prototype.build = function() { - return this.calculateAverageFieldLengths(), this.createFieldVectors(), this.createTokenSet(), new D.Index({ - invertedIndex: this.invertedIndex, - fieldVectors: this.fieldVectors, - tokenSet: this.tokenSet, - fields: Object.keys(this._fields), - pipeline: this.searchPipeline - }) - }, D.Builder.prototype.use = function(e) { - var t = Array.prototype.slice.call(arguments, 1); - t.unshift(this), e.apply(this, t) - }, D.MatchData = function(e, t, n) { - for (var r = Object.create(null), i = Object.keys(n || {}), o = 0; o < i.length; o++) { - var a = i[o]; - r[a] = n[a].slice() - } - this.metadata = Object.create(null), void 0 !== e && (this.metadata[e] = Object.create(null), this.metadata[e][t] = r) - }, D.MatchData.prototype.combine = function(e) { - for (var t = Object.keys(e.metadata), n = 0; n < t.length; n++) { - var r = t[n], - i = Object.keys(e.metadata[r]); - null == this.metadata[r] && (this.metadata[r] = Object.create(null)); - for (var o = 0; o < i.length; o++) { - var a = i[o], - s = Object.keys(e.metadata[r][a]); - null == this.metadata[r][a] && (this.metadata[r][a] = Object.create(null)); - for (var c = 0; c < s.length; c++) { - var l = s[c]; - null == this.metadata[r][a][l] ? this.metadata[r][a][l] = e.metadata[r][a][l] : this.metadata[r][a][l] = this.metadata[r][a][l].concat(e.metadata[r][a][l]) - } - } - } - }, D.MatchData.prototype.add = function(e, t, n) { - if (!(e in this.metadata)) return this.metadata[e] = Object.create(null), void(this.metadata[e][t] = n); - if (t in this.metadata[e]) - for (var r = Object.keys(n), i = 0; i < r.length; i++) { - var o = r[i]; - o in this.metadata[e][t] ? this.metadata[e][t][o] = this.metadata[e][t][o].concat(n[o]) : this.metadata[e][t][o] = n[o] - } else this.metadata[e][t] = n - }, D.Query = function(e) { - this.clauses = [], this.allFields = e - }, D.Query.wildcard = new String("*"), D.Query.wildcard.NONE = 0, D.Query.wildcard.LEADING = 1, D.Query.wildcard.TRAILING = 2, D.Query.presence = { - OPTIONAL: 1, - REQUIRED: 2, - PROHIBITED: 3 - }, D.Query.prototype.clause = function(e) { - return "fields" in e || (e.fields = this.allFields), "boost" in e || (e.boost = 1), "usePipeline" in e || (e.usePipeline = !0), "wildcard" in e || (e.wildcard = D.Query.wildcard.NONE), e.wildcard & D.Query.wildcard.LEADING && e.term.charAt(0) != D.Query.wildcard && (e.term = "*" + e.term), e.wildcard & D.Query.wildcard.TRAILING && e.term.slice(-1) != D.Query.wildcard && (e.term = e.term + "*"), "presence" in e || (e.presence = D.Query.presence.OPTIONAL), this.clauses.push(e), this - }, D.Query.prototype.isNegated = function() { - for (var e = 0; e < this.clauses.length; e++) - if (this.clauses[e].presence != D.Query.presence.PROHIBITED) return !1; - return !0 - }, D.Query.prototype.term = function(e, t) { - if (Array.isArray(e)) return e.forEach(function(e) { - this.term(e, D.utils.clone(t)) - }, this), this; - var n = t || {}; - return n.term = e.toString(), this.clause(n), this - }, D.QueryParseError = function(e, t, n) { - this.name = "QueryParseError", this.message = e, this.start = t, this.end = n - }, D.QueryParseError.prototype = new Error, D.QueryLexer = function(e) { - this.lexemes = [], this.str = e, this.length = e.length, this.pos = 0, this.start = 0, this.escapeCharPositions = [] - }, D.QueryLexer.prototype.run = function() { - for (var e = D.QueryLexer.lexText; e;) e = e(this) - }, D.QueryLexer.prototype.sliceString = function() { - for (var e = [], t = this.start, n = this.pos, r = 0; r < this.escapeCharPositions.length; r++) n = this.escapeCharPositions[r], e.push(this.str.slice(t, n)), t = n + 1; - return e.push(this.str.slice(t, this.pos)), this.escapeCharPositions.length = 0, e.join("") - }, D.QueryLexer.prototype.emit = function(e) { - this.lexemes.push({ - type: e, - str: this.sliceString(), - start: this.start, - end: this.pos - }), this.start = this.pos - }, D.QueryLexer.prototype.escapeCharacter = function() { - this.escapeCharPositions.push(this.pos - 1), this.pos += 1 - }, D.QueryLexer.prototype.next = function() { - if (this.pos >= this.length) return D.QueryLexer.EOS; - var e = this.str.charAt(this.pos); - return this.pos += 1, e - }, D.QueryLexer.prototype.width = function() { - return this.pos - this.start - }, D.QueryLexer.prototype.ignore = function() { - this.start == this.pos && (this.pos += 1), this.start = this.pos - }, D.QueryLexer.prototype.backup = function() { - this.pos -= 1 - }, D.QueryLexer.prototype.acceptDigitRun = function() { - for (var e, t; 47 < (t = (e = this.next()).charCodeAt(0)) && t < 58;); - e != D.QueryLexer.EOS && this.backup() - }, D.QueryLexer.prototype.more = function() { - return this.pos < this.length - }, D.QueryLexer.EOS = "EOS", D.QueryLexer.FIELD = "FIELD", D.QueryLexer.TERM = "TERM", D.QueryLexer.EDIT_DISTANCE = "EDIT_DISTANCE", D.QueryLexer.BOOST = "BOOST", D.QueryLexer.PRESENCE = "PRESENCE", D.QueryLexer.lexField = function(e) { - return e.backup(), e.emit(D.QueryLexer.FIELD), e.ignore(), D.QueryLexer.lexText - }, D.QueryLexer.lexTerm = function(e) { - if (1 < e.width() && (e.backup(), e.emit(D.QueryLexer.TERM)), e.ignore(), e.more()) return D.QueryLexer.lexText - }, D.QueryLexer.lexEditDistance = function(e) { - return e.ignore(), e.acceptDigitRun(), e.emit(D.QueryLexer.EDIT_DISTANCE), D.QueryLexer.lexText - }, D.QueryLexer.lexBoost = function(e) { - return e.ignore(), e.acceptDigitRun(), e.emit(D.QueryLexer.BOOST), D.QueryLexer.lexText - }, D.QueryLexer.lexEOS = function(e) { - 0 < e.width() && e.emit(D.QueryLexer.TERM) - }, D.QueryLexer.termSeparator = D.tokenizer.separator, D.QueryLexer.lexText = function(e) { - for (;;) { - var t = e.next(); - if (t == D.QueryLexer.EOS) return D.QueryLexer.lexEOS; - if (92 != t.charCodeAt(0)) { - if (":" == t) return D.QueryLexer.lexField; - if ("~" == t) return e.backup(), 0 < e.width() && e.emit(D.QueryLexer.TERM), D.QueryLexer.lexEditDistance; - if ("^" == t) return e.backup(), 0 < e.width() && e.emit(D.QueryLexer.TERM), D.QueryLexer.lexBoost; - if ("+" == t && 1 === e.width()) return e.emit(D.QueryLexer.PRESENCE), D.QueryLexer.lexText; - if ("-" == t && 1 === e.width()) return e.emit(D.QueryLexer.PRESENCE), D.QueryLexer.lexText; - if (t.match(D.QueryLexer.termSeparator)) return D.QueryLexer.lexTerm - } else e.escapeCharacter() - } - }, D.QueryParser = function(e, t) { - this.lexer = new D.QueryLexer(e), this.query = t, this.currentClause = {}, this.lexemeIdx = 0 - }, D.QueryParser.prototype.parse = function() { - this.lexer.run(), this.lexemes = this.lexer.lexemes; - for (var e = D.QueryParser.parseClause; e;) e = e(this); - return this.query - }, D.QueryParser.prototype.peekLexeme = function() { - return this.lexemes[this.lexemeIdx] - }, D.QueryParser.prototype.consumeLexeme = function() { - var e = this.peekLexeme(); - return this.lexemeIdx += 1, e - }, D.QueryParser.prototype.nextClause = function() { - var e = this.currentClause; - this.query.clause(e), this.currentClause = {} - }, D.QueryParser.parseClause = function(e) { - var t = e.peekLexeme(); - if (null != t) switch (t.type) { - case D.QueryLexer.PRESENCE: - return D.QueryParser.parsePresence; - case D.QueryLexer.FIELD: - return D.QueryParser.parseField; - case D.QueryLexer.TERM: - return D.QueryParser.parseTerm; - default: - var n = "expected either a field or a term, found " + t.type; - throw 1 <= t.str.length && (n += " with value '" + t.str + "'"), new D.QueryParseError(n, t.start, t.end) - } - }, D.QueryParser.parsePresence = function(e) { - var t = e.consumeLexeme(); - if (null != t) { - switch (t.str) { - case "-": - e.currentClause.presence = D.Query.presence.PROHIBITED; - break; - case "+": - e.currentClause.presence = D.Query.presence.REQUIRED; - break; - default: - var n = "unrecognised presence operator'" + t.str + "'"; - throw new D.QueryParseError(n, t.start, t.end) - } - var r = e.peekLexeme(); - if (null == r) { - n = "expecting term or field, found nothing"; - throw new D.QueryParseError(n, t.start, t.end) - } - switch (r.type) { - case D.QueryLexer.FIELD: - return D.QueryParser.parseField; - case D.QueryLexer.TERM: - return D.QueryParser.parseTerm; - default: - n = "expecting term or field, found '" + r.type + "'"; - throw new D.QueryParseError(n, r.start, r.end) - } - } - }, D.QueryParser.parseField = function(e) { - var t = e.consumeLexeme(); - if (null != t) { - if (-1 == e.query.allFields.indexOf(t.str)) { - var n = e.query.allFields.map(function(e) { - return "'" + e + "'" - }).join(", "), - r = "unrecognised field '" + t.str + "', possible fields: " + n; - throw new D.QueryParseError(r, t.start, t.end) - } - e.currentClause.fields = [t.str]; - var i = e.peekLexeme(); - if (null == i) { - r = "expecting term, found nothing"; - throw new D.QueryParseError(r, t.start, t.end) - } - switch (i.type) { - case D.QueryLexer.TERM: - return D.QueryParser.parseTerm; - default: - r = "expecting term, found '" + i.type + "'"; - throw new D.QueryParseError(r, i.start, i.end) - } - } - }, D.QueryParser.parseTerm = function(e) { - var t = e.consumeLexeme(); - if (null != t) { - e.currentClause.term = t.str.toLowerCase(), -1 != t.str.indexOf("*") && (e.currentClause.usePipeline = !1); - var n = e.peekLexeme(); - if (null != n) switch (n.type) { - case D.QueryLexer.TERM: - return e.nextClause(), D.QueryParser.parseTerm; - case D.QueryLexer.FIELD: - return e.nextClause(), D.QueryParser.parseField; - case D.QueryLexer.EDIT_DISTANCE: - return D.QueryParser.parseEditDistance; - case D.QueryLexer.BOOST: - return D.QueryParser.parseBoost; - case D.QueryLexer.PRESENCE: - return e.nextClause(), D.QueryParser.parsePresence; - default: - var r = "Unexpected lexeme type '" + n.type + "'"; - throw new D.QueryParseError(r, n.start, n.end) - } else e.nextClause() - } - }, D.QueryParser.parseEditDistance = function(e) { - var t = e.consumeLexeme(); - if (null != t) { - var n = parseInt(t.str, 10); - if (isNaN(n)) { - var r = "edit distance must be numeric"; - throw new D.QueryParseError(r, t.start, t.end) - } - e.currentClause.editDistance = n; - var i = e.peekLexeme(); - if (null != i) switch (i.type) { - case D.QueryLexer.TERM: - return e.nextClause(), D.QueryParser.parseTerm; - case D.QueryLexer.FIELD: - return e.nextClause(), D.QueryParser.parseField; - case D.QueryLexer.EDIT_DISTANCE: - return D.QueryParser.parseEditDistance; - case D.QueryLexer.BOOST: - return D.QueryParser.parseBoost; - case D.QueryLexer.PRESENCE: - return e.nextClause(), D.QueryParser.parsePresence; - default: - r = "Unexpected lexeme type '" + i.type + "'"; - throw new D.QueryParseError(r, i.start, i.end) - } else e.nextClause() - } - }, D.QueryParser.parseBoost = function(e) { - var t = e.consumeLexeme(); - if (null != t) { - var n = parseInt(t.str, 10); - if (isNaN(n)) { - var r = "boost must be numeric"; - throw new D.QueryParseError(r, t.start, t.end) - } - e.currentClause.boost = n; - var i = e.peekLexeme(); - if (null != i) switch (i.type) { - case D.QueryLexer.TERM: - return e.nextClause(), D.QueryParser.parseTerm; - case D.QueryLexer.FIELD: - return e.nextClause(), D.QueryParser.parseField; - case D.QueryLexer.EDIT_DISTANCE: - return D.QueryParser.parseEditDistance; - case D.QueryLexer.BOOST: - return D.QueryParser.parseBoost; - case D.QueryLexer.PRESENCE: - return e.nextClause(), D.QueryParser.parsePresence; - default: - r = "Unexpected lexeme type '" + i.type + "'"; - throw new D.QueryParseError(r, i.start, i.end) - } else e.nextClause() - } - }, void 0 === (c = "function" == typeof(s = function() { - return D - }) ? s.call(o, a, o, i) : s) || (i.exports = c) - }() -}])); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.da.js b/docs/build/html/_static/javascripts/lunr/lunr.da.js deleted file mode 100644 index 34910dfe5..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.da.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,m,i;e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=(r=e.stemmerSupport.Among,m=e.stemmerSupport.SnowballProgram,i=new function(){var i,t,n,s=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],o=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],u=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],c=new m;function l(){var e,r=c.limit-c.cursor;c.cursor>=t&&(e=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,c.find_among_b(o,4)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e)}this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var e,r=c.cursor;return function(){var e,r=c.cursor+3;if(t=c.limit,0<=r&&r<=c.limit){for(i=r;;){if(e=c.cursor,c.in_grouping(d,97,248)){c.cursor=e;break}if((c.cursor=e)>=c.limit)return;c.cursor++}for(;!c.out_grouping(d,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(t=c.cursor)=t&&(r=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,e=c.find_among_b(s,32),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:c.in_grouping_b(u,97,229)&&c.slice_del()}}(),c.cursor=c.limit,l(),c.cursor=c.limit,function(){var e,r,i,n=c.limit-c.cursor;if(c.ket=c.cursor,c.eq_s_b(2,"st")&&(c.bra=c.cursor,c.eq_s_b(2,"ig")&&c.slice_del()),c.cursor=c.limit-n,c.cursor>=t&&(r=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,e=c.find_among_b(a,5),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del(),i=c.limit-c.cursor,l(),c.cursor=c.limit-i;break;case 2:c.slice_from("løs")}}(),c.cursor=c.limit,c.cursor>=t&&(e=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,c.out_grouping_b(d,97,248)?(c.bra=c.cursor,n=c.slice_to(n),c.limit_backward=e,c.eq_v_b(n)&&c.slice_del()):c.limit_backward=e),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.de.js b/docs/build/html/_static/javascripts/lunr/lunr.de.js deleted file mode 100644 index 1529892c8..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.de.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var _,p,r;e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=(_=e.stemmerSupport.Among,p=e.stemmerSupport.SnowballProgram,r=new function(){var r,n,i,s=[new _("",-1,6),new _("U",0,2),new _("Y",0,1),new _("ä",0,3),new _("ö",0,4),new _("ü",0,5)],o=[new _("e",-1,2),new _("em",-1,1),new _("en",-1,2),new _("ern",-1,1),new _("er",-1,1),new _("s",-1,3),new _("es",5,2)],c=[new _("en",-1,1),new _("er",-1,1),new _("st",-1,2),new _("est",2,1)],u=[new _("ig",-1,1),new _("lich",-1,1)],a=[new _("end",-1,1),new _("ig",-1,2),new _("ung",-1,1),new _("lich",-1,3),new _("isch",-1,2),new _("ik",-1,2),new _("heit",-1,3),new _("keit",-1,4)],t=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],d=[117,30,5],l=[117,30,4],m=new p;function h(e,r,n){return!(!m.eq_s(1,e)||(m.ket=m.cursor,!m.in_grouping(t,97,252)))&&(m.slice_from(r),m.cursor=n,!0)}function w(){for(;!m.in_grouping(t,97,252);){if(m.cursor>=m.limit)return!0;m.cursor++}for(;!m.out_grouping(t,97,252);){if(m.cursor>=m.limit)return!0;m.cursor++}return!1}function f(){return i<=m.cursor}function b(){return n<=m.cursor}this.setCurrent=function(e){m.setCurrent(e)},this.getCurrent=function(){return m.getCurrent()},this.stem=function(){var e=m.cursor;return function(){for(var e,r,n,i,s=m.cursor;;)if(e=m.cursor,m.bra=e,m.eq_s(1,"ß"))m.ket=m.cursor,m.slice_from("ss");else{if(e>=m.limit)break;m.cursor=e+1}for(m.cursor=s;;)for(r=m.cursor;;){if(n=m.cursor,m.in_grouping(t,97,252)){if(i=m.cursor,m.bra=i,h("u","U",n))break;if(m.cursor=i,h("y","Y",n))break}if(n>=m.limit)return m.cursor=r;m.cursor=n+1}}(),m.cursor=e,function(){i=m.limit,n=i;var e=m.cursor+3;0<=e&&e<=m.limit&&(r=e,w()||((i=m.cursor)=m.limit)return;m.cursor++}}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.du.js b/docs/build/html/_static/javascripts/lunr/lunr.du.js deleted file mode 100644 index 52632004a..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.du.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var v,q,r;console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=(v=e.stemmerSupport.Among,q=e.stemmerSupport.SnowballProgram,r=new function(){var r,i,u,o=[new v("",-1,6),new v("á",0,1),new v("ä",0,1),new v("é",0,2),new v("ë",0,2),new v("í",0,3),new v("ï",0,3),new v("ó",0,4),new v("ö",0,4),new v("ú",0,5),new v("ü",0,5)],n=[new v("",-1,3),new v("I",0,2),new v("Y",0,1)],t=[new v("dd",-1,-1),new v("kk",-1,-1),new v("tt",-1,-1)],c=[new v("ene",-1,2),new v("se",-1,3),new v("en",-1,2),new v("heden",2,1),new v("s",-1,3)],a=[new v("end",-1,1),new v("ig",-1,2),new v("ing",-1,1),new v("lijk",-1,3),new v("baar",-1,4),new v("bar",-1,5)],l=[new v("aa",-1,-1),new v("ee",-1,-1),new v("oo",-1,-1),new v("uu",-1,-1)],m=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],d=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],f=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],_=new q;function s(e){return(_.cursor=e)>=_.limit||(_.cursor++,!1)}function w(){for(;!_.in_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}for(;!_.out_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}return!1}function b(){return i<=_.cursor}function p(){return r<=_.cursor}function g(){var e=_.limit-_.cursor;_.find_among_b(t,3)&&(_.cursor=_.limit-e,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del()))}function h(){var e;u=!1,_.ket=_.cursor,_.eq_s_b(1,"e")&&(_.bra=_.cursor,b()&&(e=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-e,_.slice_del(),u=!0,g())))}function k(){var e;b()&&(e=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-e,_.eq_s_b(3,"gem")||(_.cursor=_.limit-e,_.slice_del(),g())))}this.setCurrent=function(e){_.setCurrent(e)},this.getCurrent=function(){return _.getCurrent()},this.stem=function(){var e=_.cursor;return function(){for(var e,r,i,n=_.cursor;;){if(_.bra=_.cursor,e=_.find_among(o,11))switch(_.ket=_.cursor,e){case 1:_.slice_from("a");continue;case 2:_.slice_from("e");continue;case 3:_.slice_from("i");continue;case 4:_.slice_from("o");continue;case 5:_.slice_from("u");continue;case 6:if(_.cursor>=_.limit)break;_.cursor++;continue}break}for(_.cursor=n,_.bra=n,_.eq_s(1,"y")?(_.ket=_.cursor,_.slice_from("Y")):_.cursor=n;;)if(r=_.cursor,_.in_grouping(m,97,232)){if(i=_.cursor,_.bra=i,_.eq_s(1,"i"))_.ket=_.cursor,_.in_grouping(m,97,232)&&(_.slice_from("I"),_.cursor=r);else if(_.cursor=i,_.eq_s(1,"y"))_.ket=_.cursor,_.slice_from("Y"),_.cursor=r;else if(s(r))break}else if(s(r))break}(),_.cursor=e,i=_.limit,r=i,w()||((i=_.cursor)<3&&(i=3),w()||(r=_.cursor)),_.limit_backward=e,_.cursor=_.limit,function(){var e,r,i,n,o,t,s=_.limit-_.cursor;if(_.ket=_.cursor,e=_.find_among_b(c,5))switch(_.bra=_.cursor,e){case 1:b()&&_.slice_from("heid");break;case 2:k();break;case 3:b()&&_.out_grouping_b(f,97,232)&&_.slice_del()}if(_.cursor=_.limit-s,h(),_.cursor=_.limit-s,_.ket=_.cursor,_.eq_s_b(4,"heid")&&(_.bra=_.cursor,p()&&(r=_.limit-_.cursor,_.eq_s_b(1,"c")||(_.cursor=_.limit-r,_.slice_del(),_.ket=_.cursor,_.eq_s_b(2,"en")&&(_.bra=_.cursor,k())))),_.cursor=_.limit-s,_.ket=_.cursor,e=_.find_among_b(a,6))switch(_.bra=_.cursor,e){case 1:if(p()){if(_.slice_del(),i=_.limit-_.cursor,_.ket=_.cursor,_.eq_s_b(2,"ig")&&(_.bra=_.cursor,p()&&(n=_.limit-_.cursor,!_.eq_s_b(1,"e")))){_.cursor=_.limit-n,_.slice_del();break}_.cursor=_.limit-i,g()}break;case 2:p()&&(o=_.limit-_.cursor,_.eq_s_b(1,"e")||(_.cursor=_.limit-o,_.slice_del()));break;case 3:p()&&(_.slice_del(),h());break;case 4:p()&&_.slice_del();break;case 5:p()&&u&&_.slice_del()}_.cursor=_.limit-s,_.out_grouping_b(d,73,232)&&(t=_.limit-_.cursor,_.find_among_b(l,4)&&_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-t,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del())))}(),_.cursor=_.limit_backward,function(){for(var e;;)if(_.bra=_.cursor,e=_.find_among(n,3))switch(_.ket=_.cursor,e){case 1:_.slice_from("y");break;case 2:_.slice_from("i");break;case 3:if(_.cursor>=_.limit)return;_.cursor++}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.es.js b/docs/build/html/_static/javascripts/lunr/lunr.es.js deleted file mode 100644 index 9de6c09cb..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.es.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,s){"function"==typeof define&&define.amd?define(s):"object"==typeof exports?module.exports=s():s()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var C,P,s;e.es=function(){this.pipeline.reset(),this.pipeline.add(e.es.trimmer,e.es.stopWordFilter,e.es.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.es.stemmer))},e.es.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.es.trimmer=e.trimmerSupport.generateTrimmer(e.es.wordCharacters),e.Pipeline.registerFunction(e.es.trimmer,"trimmer-es"),e.es.stemmer=(C=e.stemmerSupport.Among,P=e.stemmerSupport.SnowballProgram,s=new function(){var r,n,i,a=[new C("",-1,6),new C("á",0,1),new C("é",0,2),new C("í",0,3),new C("ó",0,4),new C("ú",0,5)],t=[new C("la",-1,-1),new C("sela",0,-1),new C("le",-1,-1),new C("me",-1,-1),new C("se",-1,-1),new C("lo",-1,-1),new C("selo",5,-1),new C("las",-1,-1),new C("selas",7,-1),new C("les",-1,-1),new C("los",-1,-1),new C("selos",10,-1),new C("nos",-1,-1)],o=[new C("ando",-1,6),new C("iendo",-1,6),new C("yendo",-1,7),new C("ándo",-1,2),new C("iéndo",-1,1),new C("ar",-1,6),new C("er",-1,6),new C("ir",-1,6),new C("ár",-1,3),new C("ér",-1,4),new C("ír",-1,5)],s=[new C("ic",-1,-1),new C("ad",-1,-1),new C("os",-1,-1),new C("iv",-1,1)],u=[new C("able",-1,1),new C("ible",-1,1),new C("ante",-1,1)],w=[new C("ic",-1,1),new C("abil",-1,1),new C("iv",-1,1)],c=[new C("ica",-1,1),new C("ancia",-1,2),new C("encia",-1,5),new C("adora",-1,2),new C("osa",-1,1),new C("ista",-1,1),new C("iva",-1,9),new C("anza",-1,1),new C("logía",-1,3),new C("idad",-1,8),new C("able",-1,1),new C("ible",-1,1),new C("ante",-1,2),new C("mente",-1,7),new C("amente",13,6),new C("ación",-1,2),new C("ución",-1,4),new C("ico",-1,1),new C("ismo",-1,1),new C("oso",-1,1),new C("amiento",-1,1),new C("imiento",-1,1),new C("ivo",-1,9),new C("ador",-1,2),new C("icas",-1,1),new C("ancias",-1,2),new C("encias",-1,5),new C("adoras",-1,2),new C("osas",-1,1),new C("istas",-1,1),new C("ivas",-1,9),new C("anzas",-1,1),new C("logías",-1,3),new C("idades",-1,8),new C("ables",-1,1),new C("ibles",-1,1),new C("aciones",-1,2),new C("uciones",-1,4),new C("adores",-1,2),new C("antes",-1,2),new C("icos",-1,1),new C("ismos",-1,1),new C("osos",-1,1),new C("amientos",-1,1),new C("imientos",-1,1),new C("ivos",-1,9)],m=[new C("ya",-1,1),new C("ye",-1,1),new C("yan",-1,1),new C("yen",-1,1),new C("yeron",-1,1),new C("yendo",-1,1),new C("yo",-1,1),new C("yas",-1,1),new C("yes",-1,1),new C("yais",-1,1),new C("yamos",-1,1),new C("yó",-1,1)],l=[new C("aba",-1,2),new C("ada",-1,2),new C("ida",-1,2),new C("ara",-1,2),new C("iera",-1,2),new C("ía",-1,2),new C("aría",5,2),new C("ería",5,2),new C("iría",5,2),new C("ad",-1,2),new C("ed",-1,2),new C("id",-1,2),new C("ase",-1,2),new C("iese",-1,2),new C("aste",-1,2),new C("iste",-1,2),new C("an",-1,2),new C("aban",16,2),new C("aran",16,2),new C("ieran",16,2),new C("ían",16,2),new C("arían",20,2),new C("erían",20,2),new C("irían",20,2),new C("en",-1,1),new C("asen",24,2),new C("iesen",24,2),new C("aron",-1,2),new C("ieron",-1,2),new C("arán",-1,2),new C("erán",-1,2),new C("irán",-1,2),new C("ado",-1,2),new C("ido",-1,2),new C("ando",-1,2),new C("iendo",-1,2),new C("ar",-1,2),new C("er",-1,2),new C("ir",-1,2),new C("as",-1,2),new C("abas",39,2),new C("adas",39,2),new C("idas",39,2),new C("aras",39,2),new C("ieras",39,2),new C("ías",39,2),new C("arías",45,2),new C("erías",45,2),new C("irías",45,2),new C("es",-1,1),new C("ases",49,2),new C("ieses",49,2),new C("abais",-1,2),new C("arais",-1,2),new C("ierais",-1,2),new C("íais",-1,2),new C("aríais",55,2),new C("eríais",55,2),new C("iríais",55,2),new C("aseis",-1,2),new C("ieseis",-1,2),new C("asteis",-1,2),new C("isteis",-1,2),new C("áis",-1,2),new C("éis",-1,1),new C("aréis",64,2),new C("eréis",64,2),new C("iréis",64,2),new C("ados",-1,2),new C("idos",-1,2),new C("amos",-1,2),new C("ábamos",70,2),new C("áramos",70,2),new C("iéramos",70,2),new C("íamos",70,2),new C("aríamos",74,2),new C("eríamos",74,2),new C("iríamos",74,2),new C("emos",-1,1),new C("aremos",78,2),new C("eremos",78,2),new C("iremos",78,2),new C("ásemos",78,2),new C("iésemos",78,2),new C("imos",-1,2),new C("arás",-1,2),new C("erás",-1,2),new C("irás",-1,2),new C("ís",-1,2),new C("ará",-1,2),new C("erá",-1,2),new C("irá",-1,2),new C("aré",-1,2),new C("eré",-1,2),new C("iré",-1,2),new C("ió",-1,2)],d=[new C("a",-1,1),new C("e",-1,2),new C("o",-1,1),new C("os",-1,1),new C("á",-1,1),new C("é",-1,2),new C("í",-1,1),new C("ó",-1,1)],b=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],f=new P;function _(){if(f.out_grouping(b,97,252)){for(;!f.in_grouping(b,97,252);){if(f.cursor>=f.limit)return!0;f.cursor++}return!1}return!0}function h(){var e,s=f.cursor;if(function(){if(f.in_grouping(b,97,252)){var e=f.cursor;if(_()){if(f.cursor=e,!f.in_grouping(b,97,252))return!0;for(;!f.out_grouping(b,97,252);){if(f.cursor>=f.limit)return!0;f.cursor++}}return!1}return!0}()){if(f.cursor=s,!f.out_grouping(b,97,252))return;if(e=f.cursor,_()){if(f.cursor=e,!f.in_grouping(b,97,252)||f.cursor>=f.limit)return;f.cursor++}}i=f.cursor}function v(){for(;!f.in_grouping(b,97,252);){if(f.cursor>=f.limit)return!1;f.cursor++}for(;!f.out_grouping(b,97,252);){if(f.cursor>=f.limit)return!1;f.cursor++}return!0}function p(){return i<=f.cursor}function g(){return r<=f.cursor}function k(e,s){if(!g())return!0;f.slice_del(),f.ket=f.cursor;var r=f.find_among_b(e,s);return r&&(f.bra=f.cursor,1==r&&g()&&f.slice_del()),!1}function y(e){return!g()||(f.slice_del(),f.ket=f.cursor,f.eq_s_b(2,e)&&(f.bra=f.cursor,g()&&f.slice_del()),!1)}function q(){var e;if(f.ket=f.cursor,e=f.find_among_b(c,46)){switch(f.bra=f.cursor,e){case 1:if(!g())return!1;f.slice_del();break;case 2:if(y("ic"))return!1;break;case 3:if(!g())return!1;f.slice_from("log");break;case 4:if(!g())return!1;f.slice_from("u");break;case 5:if(!g())return!1;f.slice_from("ente");break;case 6:if(!(n<=f.cursor))return!1;f.slice_del(),f.ket=f.cursor,(e=f.find_among_b(s,4))&&(f.bra=f.cursor,g()&&(f.slice_del(),1==e&&(f.ket=f.cursor,f.eq_s_b(2,"at")&&(f.bra=f.cursor,g()&&f.slice_del()))));break;case 7:if(k(u,3))return!1;break;case 8:if(k(w,3))return!1;break;case 9:if(y("at"))return!1}return!0}return!1}this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var e,s=f.cursor;return e=f.cursor,i=f.limit,r=n=i,h(),f.cursor=e,v()&&(n=f.cursor,v()&&(r=f.cursor)),f.limit_backward=s,f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,f.find_among_b(t,13)&&(f.bra=f.cursor,(e=f.find_among_b(o,11))&&p()))switch(e){case 1:f.bra=f.cursor,f.slice_from("iendo");break;case 2:f.bra=f.cursor,f.slice_from("ando");break;case 3:f.bra=f.cursor,f.slice_from("ar");break;case 4:f.bra=f.cursor,f.slice_from("er");break;case 5:f.bra=f.cursor,f.slice_from("ir");break;case 6:f.slice_del();break;case 7:f.eq_s_b(1,"u")&&f.slice_del()}}(),f.cursor=f.limit,q()||(f.cursor=f.limit,function(){var e,s;if(f.cursor>=i&&(s=f.limit_backward,f.limit_backward=i,f.ket=f.cursor,e=f.find_among_b(m,12),f.limit_backward=s,e)){if(f.bra=f.cursor,1==e){if(!f.eq_s_b(1,"u"))return!1;f.slice_del()}return!0}return!1}()||(f.cursor=f.limit,function(){var e,s,r,n;if(f.cursor>=i&&(s=f.limit_backward,f.limit_backward=i,f.ket=f.cursor,e=f.find_among_b(l,96),f.limit_backward=s,e))switch(f.bra=f.cursor,e){case 1:r=f.limit-f.cursor,f.eq_s_b(1,"u")?(n=f.limit-f.cursor,f.eq_s_b(1,"g")?f.cursor=f.limit-n:f.cursor=f.limit-r):f.cursor=f.limit-r,f.bra=f.cursor;case 2:f.slice_del()}}())),f.cursor=f.limit,function(){var e,s;if(f.ket=f.cursor,e=f.find_among_b(d,8))switch(f.bra=f.cursor,e){case 1:p()&&f.slice_del();break;case 2:p()&&(f.slice_del(),f.ket=f.cursor,f.eq_s_b(1,"u")&&(f.bra=f.cursor,s=f.limit-f.cursor,f.eq_s_b(1,"g")&&(f.cursor=f.limit-s,p()&&f.slice_del())))}}(),f.cursor=f.limit_backward,function(){for(var e;;){if(f.bra=f.cursor,e=f.find_among(a,6))switch(f.ket=f.cursor,e){case 1:f.slice_from("a");continue;case 2:f.slice_from("e");continue;case 3:f.slice_from("i");continue;case 4:f.slice_from("o");continue;case 5:f.slice_from("u");continue;case 6:if(f.cursor>=f.limit)break;f.cursor++;continue}break}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return s.setCurrent(e),s.stem(),s.getCurrent()}):(s.setCurrent(e),s.stem(),s.getCurrent())}),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.fi.js b/docs/build/html/_static/javascripts/lunr/lunr.fi.js deleted file mode 100644 index 2f9bf5aeb..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.fi.js +++ /dev/null @@ -1 +0,0 @@ -!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var v,C,e;i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=(v=i.stemmerSupport.Among,C=i.stemmerSupport.SnowballProgram,e=new function(){var n,t,l,o,r=[new v("pa",-1,1),new v("sti",-1,2),new v("kaan",-1,1),new v("han",-1,1),new v("kin",-1,1),new v("hän",-1,1),new v("kään",-1,1),new v("ko",-1,1),new v("pä",-1,1),new v("kö",-1,1)],s=[new v("lla",-1,-1),new v("na",-1,-1),new v("ssa",-1,-1),new v("ta",-1,-1),new v("lta",3,-1),new v("sta",3,-1)],a=[new v("llä",-1,-1),new v("nä",-1,-1),new v("ssä",-1,-1),new v("tä",-1,-1),new v("ltä",3,-1),new v("stä",3,-1)],u=[new v("lle",-1,-1),new v("ine",-1,-1)],c=[new v("nsa",-1,3),new v("mme",-1,3),new v("nne",-1,3),new v("ni",-1,2),new v("si",-1,1),new v("an",-1,4),new v("en",-1,6),new v("än",-1,5),new v("nsä",-1,3)],i=[new v("aa",-1,-1),new v("ee",-1,-1),new v("ii",-1,-1),new v("oo",-1,-1),new v("uu",-1,-1),new v("ää",-1,-1),new v("öö",-1,-1)],m=[new v("a",-1,8),new v("lla",0,-1),new v("na",0,-1),new v("ssa",0,-1),new v("ta",0,-1),new v("lta",4,-1),new v("sta",4,-1),new v("tta",4,9),new v("lle",-1,-1),new v("ine",-1,-1),new v("ksi",-1,-1),new v("n",-1,7),new v("han",11,1),new v("den",11,-1,q),new v("seen",11,-1,j),new v("hen",11,2),new v("tten",11,-1,q),new v("hin",11,3),new v("siin",11,-1,q),new v("hon",11,4),new v("hän",11,5),new v("hön",11,6),new v("ä",-1,8),new v("llä",22,-1),new v("nä",22,-1),new v("ssä",22,-1),new v("tä",22,-1),new v("ltä",26,-1),new v("stä",26,-1),new v("ttä",26,9)],w=[new v("eja",-1,-1),new v("mma",-1,1),new v("imma",1,-1),new v("mpa",-1,1),new v("impa",3,-1),new v("mmi",-1,1),new v("immi",5,-1),new v("mpi",-1,1),new v("impi",7,-1),new v("ejä",-1,-1),new v("mmä",-1,1),new v("immä",10,-1),new v("mpä",-1,1),new v("impä",12,-1)],_=[new v("i",-1,-1),new v("j",-1,-1)],k=[new v("mma",-1,1),new v("imma",0,-1)],b=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],e=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],f=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],h=new C;function p(){for(var i;i=h.cursor,!h.in_grouping(d,97,246);){if((h.cursor=i)>=h.limit)return!0;h.cursor++}for(h.cursor=i;!h.out_grouping(d,97,246);){if(h.cursor>=h.limit)return!0;h.cursor++}return!1}function g(){var i,e;if(h.cursor>=o)if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,i=h.find_among_b(r,10)){switch(h.bra=h.cursor,h.limit_backward=e,i){case 1:if(!h.in_grouping_b(f,97,246))return;break;case 2:if(!(l<=h.cursor))return}h.slice_del()}else h.limit_backward=e}function j(){return h.find_among_b(i,7)}function q(){return h.eq_s_b(1,"i")&&h.in_grouping_b(e,97,246)}this.setCurrent=function(i){h.setCurrent(i)},this.getCurrent=function(){return h.getCurrent()},this.stem=function(){var i,e=h.cursor;return o=h.limit,l=o,p()||(o=h.cursor,p()||(l=h.cursor)),n=!1,h.limit_backward=e,h.cursor=h.limit,g(),h.cursor=h.limit,function(){var i,e,r;if(h.cursor>=o)if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,i=h.find_among_b(c,9))switch(h.bra=h.cursor,h.limit_backward=e,i){case 1:r=h.limit-h.cursor,h.eq_s_b(1,"k")||(h.cursor=h.limit-r,h.slice_del());break;case 2:h.slice_del(),h.ket=h.cursor,h.eq_s_b(3,"kse")&&(h.bra=h.cursor,h.slice_from("ksi"));break;case 3:h.slice_del();break;case 4:h.find_among_b(s,6)&&h.slice_del();break;case 5:h.find_among_b(a,6)&&h.slice_del();break;case 6:h.find_among_b(u,2)&&h.slice_del()}else h.limit_backward=e}(),h.cursor=h.limit,function(){var i,e,r;if(h.cursor>=o)if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,i=h.find_among_b(m,30)){switch(h.bra=h.cursor,h.limit_backward=e,i){case 1:if(!h.eq_s_b(1,"a"))return;break;case 2:case 9:if(!h.eq_s_b(1,"e"))return;break;case 3:if(!h.eq_s_b(1,"i"))return;break;case 4:if(!h.eq_s_b(1,"o"))return;break;case 5:if(!h.eq_s_b(1,"ä"))return;break;case 6:if(!h.eq_s_b(1,"ö"))return;break;case 7:if(r=h.limit-h.cursor,!j()&&(h.cursor=h.limit-r,!h.eq_s_b(2,"ie"))){h.cursor=h.limit-r;break}if(h.cursor=h.limit-r,h.cursor<=h.limit_backward){h.cursor=h.limit-r;break}h.cursor--,h.bra=h.cursor;break;case 8:if(!h.in_grouping_b(d,97,246)||!h.out_grouping_b(d,97,246))return}h.slice_del(),n=!0}else h.limit_backward=e}(),h.cursor=h.limit,function(){var i,e,r;if(h.cursor>=l)if(e=h.limit_backward,h.limit_backward=l,h.ket=h.cursor,i=h.find_among_b(w,14)){if(h.bra=h.cursor,h.limit_backward=e,1==i){if(r=h.limit-h.cursor,h.eq_s_b(2,"po"))return;h.cursor=h.limit-r}h.slice_del()}else h.limit_backward=e}(),h.cursor=h.limit,h.cursor=(n?h.cursor>=o&&(i=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,h.find_among_b(_,2)?(h.bra=h.cursor,h.limit_backward=i,h.slice_del()):h.limit_backward=i):(h.cursor=h.limit,function(){var i,e,r,n,t,s;if(h.cursor>=o){if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,h.eq_s_b(1,"t")&&(h.bra=h.cursor,r=h.limit-h.cursor,h.in_grouping_b(d,97,246)&&(h.cursor=h.limit-r,h.slice_del(),h.limit_backward=e,n=h.limit-h.cursor,h.cursor>=l&&(h.cursor=l,t=h.limit_backward,h.limit_backward=h.cursor,h.cursor=h.limit-n,h.ket=h.cursor,i=h.find_among_b(k,2))))){if(h.bra=h.cursor,h.limit_backward=t,1==i){if(s=h.limit-h.cursor,h.eq_s_b(2,"po"))return;h.cursor=h.limit-s}return h.slice_del()}h.limit_backward=e}}()),h.limit),function(){var i,e,r,n;if(h.cursor>=o){for(i=h.limit_backward,h.limit_backward=o,e=h.limit-h.cursor,j()&&(h.cursor=h.limit-e,h.ket=h.cursor,h.cursor>h.limit_backward&&(h.cursor--,h.bra=h.cursor,h.slice_del())),h.cursor=h.limit-e,h.ket=h.cursor,h.in_grouping_b(b,97,228)&&(h.bra=h.cursor,h.out_grouping_b(d,97,246)&&h.slice_del()),h.cursor=h.limit-e,h.ket=h.cursor,h.eq_s_b(1,"j")&&(h.bra=h.cursor,r=h.limit-h.cursor,h.eq_s_b(1,"o")?h.slice_del():(h.cursor=h.limit-r,h.eq_s_b(1,"u")&&h.slice_del())),h.cursor=h.limit-e,h.ket=h.cursor,h.eq_s_b(1,"o")&&(h.bra=h.cursor,h.eq_s_b(1,"j")&&h.slice_del()),h.cursor=h.limit-e,h.limit_backward=i;;){if(n=h.limit-h.cursor,h.out_grouping_b(d,97,246)){h.cursor=h.limit-n;break}if(h.cursor=h.limit-n,h.cursor<=h.limit_backward)return;h.cursor--}h.ket=h.cursor,h.cursor>h.limit_backward&&(h.cursor--,h.bra=h.cursor,t=h.slice_to(),h.eq_v_b(t)&&h.slice_del())}}(),!0}},function(i){return"function"==typeof i.update?i.update(function(i){return e.setCurrent(i),e.stem(),e.getCurrent()}):(e.setCurrent(i),e.stem(),e.getCurrent())}),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.fr.js b/docs/build/html/_static/javascripts/lunr/lunr.fr.js deleted file mode 100644 index 078d0cab7..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.fr.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,y,s;e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=(r=e.stemmerSupport.Among,y=e.stemmerSupport.SnowballProgram,s=new function(){var s,i,t,n=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],u=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],o=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],c=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],a=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],l=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],w=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],f=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],m=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],_=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],b=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],d=new y;function k(e,r,s){return!(!d.eq_s(1,e)||(d.ket=d.cursor,!d.in_grouping(_,97,251)))&&(d.slice_from(r),d.cursor=s,!0)}function p(e,r,s){return!!d.eq_s(1,e)&&(d.ket=d.cursor,d.slice_from(r),d.cursor=s,!0)}function g(){for(;!d.in_grouping(_,97,251);){if(d.cursor>=d.limit)return!0;d.cursor++}for(;!d.out_grouping(_,97,251);){if(d.cursor>=d.limit)return!0;d.cursor++}return!1}function q(){return t<=d.cursor}function v(){return i<=d.cursor}function h(){return s<=d.cursor}function z(){if(!function(){var e,r;if(d.ket=d.cursor,e=d.find_among_b(a,43)){switch(d.bra=d.cursor,e){case 1:if(!h())return!1;d.slice_del();break;case 2:if(!h())return!1;d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"ic")&&(d.bra=d.cursor,h()?d.slice_del():d.slice_from("iqU"));break;case 3:if(!h())return!1;d.slice_from("log");break;case 4:if(!h())return!1;d.slice_from("u");break;case 5:if(!h())return!1;d.slice_from("ent");break;case 6:if(!q())return!1;if(d.slice_del(),d.ket=d.cursor,e=d.find_among_b(o,6))switch(d.bra=d.cursor,e){case 1:h()&&(d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,h()&&d.slice_del()));break;case 2:h()?d.slice_del():v()&&d.slice_from("eux");break;case 3:h()&&d.slice_del();break;case 4:q()&&d.slice_from("i")}break;case 7:if(!h())return!1;if(d.slice_del(),d.ket=d.cursor,e=d.find_among_b(c,3))switch(d.bra=d.cursor,e){case 1:h()?d.slice_del():d.slice_from("abl");break;case 2:h()?d.slice_del():d.slice_from("iqU");break;case 3:h()&&d.slice_del()}break;case 8:if(!h())return!1;if(d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,h()&&(d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"ic")))){d.bra=d.cursor,h()?d.slice_del():d.slice_from("iqU");break}break;case 9:d.slice_from("eau");break;case 10:if(!v())return!1;d.slice_from("al");break;case 11:if(h())d.slice_del();else{if(!v())return!1;d.slice_from("eux")}break;case 12:if(!v()||!d.out_grouping_b(_,97,251))return!1;d.slice_del();break;case 13:return q()&&d.slice_from("ant"),!1;case 14:return q()&&d.slice_from("ent"),!1;case 15:return r=d.limit-d.cursor,d.in_grouping_b(_,97,251)&&q()&&(d.cursor=d.limit-r,d.slice_del()),!1}return!0}return!1}()&&(d.cursor=d.limit,!function(){var e,r;if(d.cursor=t){if(s=d.limit_backward,d.limit_backward=t,d.ket=d.cursor,e=d.find_among_b(f,7))switch(d.bra=d.cursor,e){case 1:if(h()){if(i=d.limit-d.cursor,!d.eq_s_b(1,"s")&&(d.cursor=d.limit-i,!d.eq_s_b(1,"t")))break;d.slice_del()}break;case 2:d.slice_from("i");break;case 3:d.slice_del();break;case 4:d.eq_s_b(2,"gu")&&d.slice_del()}d.limit_backward=s}}();d.cursor=d.limit,d.ket=d.cursor,d.eq_s_b(1,"Y")?(d.bra=d.cursor,d.slice_from("i")):(d.cursor=d.limit,d.eq_s_b(1,"ç")&&(d.bra=d.cursor,d.slice_from("c")))}this.setCurrent=function(e){d.setCurrent(e)},this.getCurrent=function(){return d.getCurrent()},this.stem=function(){var e,r=d.cursor;return function(){for(var e,r;;){if(e=d.cursor,d.in_grouping(_,97,251)){if(d.bra=d.cursor,r=d.cursor,k("u","U",e))continue;if(d.cursor=r,k("i","I",e))continue;if(d.cursor=r,p("y","Y",e))continue}if(d.cursor=e,!k("y","Y",d.bra=e)){if(d.cursor=e,d.eq_s(1,"q")&&(d.bra=d.cursor,p("u","U",e)))continue;if((d.cursor=e)>=d.limit)return;d.cursor++}}}(),d.cursor=r,function(){var e=d.cursor;if(t=d.limit,s=i=t,d.in_grouping(_,97,251)&&d.in_grouping(_,97,251)&&d.cursor=d.limit){d.cursor=t;break}d.cursor++}while(!d.in_grouping(_,97,251))}t=d.cursor,d.cursor=e,g()||(i=d.cursor,g()||(s=d.cursor))}(),d.limit_backward=r,d.cursor=d.limit,z(),d.cursor=d.limit,e=d.limit-d.cursor,d.find_among_b(m,5)&&(d.cursor=d.limit-e,d.ket=d.cursor,d.cursor>d.limit_backward&&(d.cursor--,d.bra=d.cursor,d.slice_del())),d.cursor=d.limit,function(){for(var e,r=1;d.out_grouping_b(_,97,251);)r--;if(r<=0){if(d.ket=d.cursor,e=d.limit-d.cursor,!d.eq_s_b(1,"é")&&(d.cursor=d.limit-e,!d.eq_s_b(1,"è")))return;d.bra=d.cursor,d.slice_from("e")}}(),d.cursor=d.limit_backward,function(){for(var e,r;r=d.cursor,d.bra=r,e=d.find_among(u,4);)switch(d.ket=d.cursor,e){case 1:d.slice_from("i");break;case 2:d.slice_from("u");break;case 3:d.slice_from("y");break;case 4:if(d.cursor>=d.limit)return;d.cursor++}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return s.setCurrent(e),s.stem(),s.getCurrent()}):(s.setCurrent(e),s.stem(),s.getCurrent())}),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.hu.js b/docs/build/html/_static/javascripts/lunr/lunr.hu.js deleted file mode 100644 index 56a4b0dc1..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.hu.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var p,_,n;e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=(p=e.stemmerSupport.Among,_=e.stemmerSupport.SnowballProgram,n=new function(){var r,i=[new p("cs",-1,-1),new p("dzs",-1,-1),new p("gy",-1,-1),new p("ly",-1,-1),new p("ny",-1,-1),new p("sz",-1,-1),new p("ty",-1,-1),new p("zs",-1,-1)],n=[new p("á",-1,1),new p("é",-1,2)],a=[new p("bb",-1,-1),new p("cc",-1,-1),new p("dd",-1,-1),new p("ff",-1,-1),new p("gg",-1,-1),new p("jj",-1,-1),new p("kk",-1,-1),new p("ll",-1,-1),new p("mm",-1,-1),new p("nn",-1,-1),new p("pp",-1,-1),new p("rr",-1,-1),new p("ccs",-1,-1),new p("ss",-1,-1),new p("zzs",-1,-1),new p("tt",-1,-1),new p("vv",-1,-1),new p("ggy",-1,-1),new p("lly",-1,-1),new p("nny",-1,-1),new p("tty",-1,-1),new p("ssz",-1,-1),new p("zz",-1,-1)],t=[new p("al",-1,1),new p("el",-1,2)],e=[new p("ba",-1,-1),new p("ra",-1,-1),new p("be",-1,-1),new p("re",-1,-1),new p("ig",-1,-1),new p("nak",-1,-1),new p("nek",-1,-1),new p("val",-1,-1),new p("vel",-1,-1),new p("ul",-1,-1),new p("nál",-1,-1),new p("nél",-1,-1),new p("ból",-1,-1),new p("ról",-1,-1),new p("tól",-1,-1),new p("bõl",-1,-1),new p("rõl",-1,-1),new p("tõl",-1,-1),new p("ül",-1,-1),new p("n",-1,-1),new p("an",19,-1),new p("ban",20,-1),new p("en",19,-1),new p("ben",22,-1),new p("képpen",22,-1),new p("on",19,-1),new p("ön",19,-1),new p("képp",-1,-1),new p("kor",-1,-1),new p("t",-1,-1),new p("at",29,-1),new p("et",29,-1),new p("ként",29,-1),new p("anként",32,-1),new p("enként",32,-1),new p("onként",32,-1),new p("ot",29,-1),new p("ért",29,-1),new p("öt",29,-1),new p("hez",-1,-1),new p("hoz",-1,-1),new p("höz",-1,-1),new p("vá",-1,-1),new p("vé",-1,-1)],s=[new p("án",-1,2),new p("én",-1,1),new p("ánként",-1,3)],c=[new p("stul",-1,2),new p("astul",0,1),new p("ástul",0,3),new p("stül",-1,2),new p("estül",3,1),new p("éstül",3,4)],w=[new p("á",-1,1),new p("é",-1,2)],o=[new p("k",-1,7),new p("ak",0,4),new p("ek",0,6),new p("ok",0,5),new p("ák",0,1),new p("ék",0,2),new p("ök",0,3)],l=[new p("éi",-1,7),new p("áéi",0,6),new p("ééi",0,5),new p("é",-1,9),new p("ké",3,4),new p("aké",4,1),new p("eké",4,1),new p("oké",4,1),new p("áké",4,3),new p("éké",4,2),new p("öké",4,1),new p("éé",3,8)],u=[new p("a",-1,18),new p("ja",0,17),new p("d",-1,16),new p("ad",2,13),new p("ed",2,13),new p("od",2,13),new p("ád",2,14),new p("éd",2,15),new p("öd",2,13),new p("e",-1,18),new p("je",9,17),new p("nk",-1,4),new p("unk",11,1),new p("ánk",11,2),new p("énk",11,3),new p("ünk",11,1),new p("uk",-1,8),new p("juk",16,7),new p("ájuk",17,5),new p("ük",-1,8),new p("jük",19,7),new p("éjük",20,6),new p("m",-1,12),new p("am",22,9),new p("em",22,9),new p("om",22,9),new p("ám",22,10),new p("ém",22,11),new p("o",-1,18),new p("á",-1,19),new p("é",-1,20)],m=[new p("id",-1,10),new p("aid",0,9),new p("jaid",1,6),new p("eid",0,9),new p("jeid",3,6),new p("áid",0,7),new p("éid",0,8),new p("i",-1,15),new p("ai",7,14),new p("jai",8,11),new p("ei",7,14),new p("jei",10,11),new p("ái",7,12),new p("éi",7,13),new p("itek",-1,24),new p("eitek",14,21),new p("jeitek",15,20),new p("éitek",14,23),new p("ik",-1,29),new p("aik",18,26),new p("jaik",19,25),new p("eik",18,26),new p("jeik",21,25),new p("áik",18,27),new p("éik",18,28),new p("ink",-1,20),new p("aink",25,17),new p("jaink",26,16),new p("eink",25,17),new p("jeink",28,16),new p("áink",25,18),new p("éink",25,19),new p("aitok",-1,21),new p("jaitok",32,20),new p("áitok",-1,22),new p("im",-1,5),new p("aim",35,4),new p("jaim",36,1),new p("eim",35,4),new p("jeim",38,1),new p("áim",35,2),new p("éim",35,3)],k=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],f=new _;function b(){return r<=f.cursor}function d(){var e=f.limit-f.cursor;return!!f.find_among_b(a,23)&&(f.cursor=f.limit-e,!0)}function g(){if(f.cursor>f.limit_backward){f.cursor--,f.ket=f.cursor;var e=f.cursor-1;f.limit_backward<=e&&e<=f.limit&&(f.cursor=e,f.bra=e,f.slice_del())}}function h(){f.ket=f.cursor,f.find_among_b(e,44)&&(f.bra=f.cursor,b()&&(f.slice_del(),function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(n,2))&&(f.bra=f.cursor,b()))switch(e){case 1:f.slice_from("a");break;case 2:f.slice_from("e")}}()))}this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var e=f.cursor;return function(){var e,n=f.cursor;if(r=f.limit,f.in_grouping(k,97,252))for(;;){if(e=f.cursor,f.out_grouping(k,97,252))return f.cursor=e,f.find_among(i,8)||(f.cursor=e)=f.limit)return r=e;f.cursor++}if(f.cursor=n,f.out_grouping(k,97,252)){for(;!f.in_grouping(k,97,252);){if(f.cursor>=f.limit)return;f.cursor++}r=f.cursor}}(),f.limit_backward=e,f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(t,2))&&(f.bra=f.cursor,b())){if((1==e||2==e)&&!d())return;f.slice_del(),g()}}(),f.cursor=f.limit,h(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(s,3))&&(f.bra=f.cursor,b()))switch(e){case 1:f.slice_from("e");break;case 2:case 3:f.slice_from("a")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(c,6))&&(f.bra=f.cursor,b()))switch(e){case 1:case 2:f.slice_del();break;case 3:f.slice_from("a");break;case 4:f.slice_from("e")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(w,2))&&(f.bra=f.cursor,b())){if((1==e||2==e)&&!d())return;f.slice_del(),g()}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(l,12))&&(f.bra=f.cursor,b()))switch(e){case 1:case 4:case 7:case 9:f.slice_del();break;case 2:case 5:case 8:f.slice_from("e");break;case 3:case 6:f.slice_from("a")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(u,31))&&(f.bra=f.cursor,b()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:f.slice_del();break;case 2:case 5:case 10:case 14:case 19:f.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:f.slice_from("e")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(m,42))&&(f.bra=f.cursor,b()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:f.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:f.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:f.slice_from("e")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(o,7))&&(f.bra=f.cursor,b()))switch(e){case 1:f.slice_from("a");break;case 2:f.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:f.slice_del()}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.it.js b/docs/build/html/_static/javascripts/lunr/lunr.it.js deleted file mode 100644 index 50dddaa04..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.it.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var z,P,r;e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=(z=e.stemmerSupport.Among,P=e.stemmerSupport.SnowballProgram,r=new function(){var o,t,s,a=[new z("",-1,7),new z("qu",0,6),new z("á",0,1),new z("é",0,2),new z("í",0,3),new z("ó",0,4),new z("ú",0,5)],u=[new z("",-1,3),new z("I",0,1),new z("U",0,2)],c=[new z("la",-1,-1),new z("cela",0,-1),new z("gliela",0,-1),new z("mela",0,-1),new z("tela",0,-1),new z("vela",0,-1),new z("le",-1,-1),new z("cele",6,-1),new z("gliele",6,-1),new z("mele",6,-1),new z("tele",6,-1),new z("vele",6,-1),new z("ne",-1,-1),new z("cene",12,-1),new z("gliene",12,-1),new z("mene",12,-1),new z("sene",12,-1),new z("tene",12,-1),new z("vene",12,-1),new z("ci",-1,-1),new z("li",-1,-1),new z("celi",20,-1),new z("glieli",20,-1),new z("meli",20,-1),new z("teli",20,-1),new z("veli",20,-1),new z("gli",20,-1),new z("mi",-1,-1),new z("si",-1,-1),new z("ti",-1,-1),new z("vi",-1,-1),new z("lo",-1,-1),new z("celo",31,-1),new z("glielo",31,-1),new z("melo",31,-1),new z("telo",31,-1),new z("velo",31,-1)],w=[new z("ando",-1,1),new z("endo",-1,1),new z("ar",-1,2),new z("er",-1,2),new z("ir",-1,2)],r=[new z("ic",-1,-1),new z("abil",-1,-1),new z("os",-1,-1),new z("iv",-1,1)],n=[new z("ic",-1,1),new z("abil",-1,1),new z("iv",-1,1)],i=[new z("ica",-1,1),new z("logia",-1,3),new z("osa",-1,1),new z("ista",-1,1),new z("iva",-1,9),new z("anza",-1,1),new z("enza",-1,5),new z("ice",-1,1),new z("atrice",7,1),new z("iche",-1,1),new z("logie",-1,3),new z("abile",-1,1),new z("ibile",-1,1),new z("usione",-1,4),new z("azione",-1,2),new z("uzione",-1,4),new z("atore",-1,2),new z("ose",-1,1),new z("ante",-1,1),new z("mente",-1,1),new z("amente",19,7),new z("iste",-1,1),new z("ive",-1,9),new z("anze",-1,1),new z("enze",-1,5),new z("ici",-1,1),new z("atrici",25,1),new z("ichi",-1,1),new z("abili",-1,1),new z("ibili",-1,1),new z("ismi",-1,1),new z("usioni",-1,4),new z("azioni",-1,2),new z("uzioni",-1,4),new z("atori",-1,2),new z("osi",-1,1),new z("anti",-1,1),new z("amenti",-1,6),new z("imenti",-1,6),new z("isti",-1,1),new z("ivi",-1,9),new z("ico",-1,1),new z("ismo",-1,1),new z("oso",-1,1),new z("amento",-1,6),new z("imento",-1,6),new z("ivo",-1,9),new z("ità",-1,8),new z("istà",-1,1),new z("istè",-1,1),new z("istì",-1,1)],l=[new z("isca",-1,1),new z("enda",-1,1),new z("ata",-1,1),new z("ita",-1,1),new z("uta",-1,1),new z("ava",-1,1),new z("eva",-1,1),new z("iva",-1,1),new z("erebbe",-1,1),new z("irebbe",-1,1),new z("isce",-1,1),new z("ende",-1,1),new z("are",-1,1),new z("ere",-1,1),new z("ire",-1,1),new z("asse",-1,1),new z("ate",-1,1),new z("avate",16,1),new z("evate",16,1),new z("ivate",16,1),new z("ete",-1,1),new z("erete",20,1),new z("irete",20,1),new z("ite",-1,1),new z("ereste",-1,1),new z("ireste",-1,1),new z("ute",-1,1),new z("erai",-1,1),new z("irai",-1,1),new z("isci",-1,1),new z("endi",-1,1),new z("erei",-1,1),new z("irei",-1,1),new z("assi",-1,1),new z("ati",-1,1),new z("iti",-1,1),new z("eresti",-1,1),new z("iresti",-1,1),new z("uti",-1,1),new z("avi",-1,1),new z("evi",-1,1),new z("ivi",-1,1),new z("isco",-1,1),new z("ando",-1,1),new z("endo",-1,1),new z("Yamo",-1,1),new z("iamo",-1,1),new z("avamo",-1,1),new z("evamo",-1,1),new z("ivamo",-1,1),new z("eremo",-1,1),new z("iremo",-1,1),new z("assimo",-1,1),new z("ammo",-1,1),new z("emmo",-1,1),new z("eremmo",54,1),new z("iremmo",54,1),new z("immo",-1,1),new z("ano",-1,1),new z("iscano",58,1),new z("avano",58,1),new z("evano",58,1),new z("ivano",58,1),new z("eranno",-1,1),new z("iranno",-1,1),new z("ono",-1,1),new z("iscono",65,1),new z("arono",65,1),new z("erono",65,1),new z("irono",65,1),new z("erebbero",-1,1),new z("irebbero",-1,1),new z("assero",-1,1),new z("essero",-1,1),new z("issero",-1,1),new z("ato",-1,1),new z("ito",-1,1),new z("uto",-1,1),new z("avo",-1,1),new z("evo",-1,1),new z("ivo",-1,1),new z("ar",-1,1),new z("ir",-1,1),new z("erà",-1,1),new z("irà",-1,1),new z("erò",-1,1),new z("irò",-1,1)],m=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],f=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],v=[17],b=new P;function d(e,r,n){return!(!b.eq_s(1,e)||(b.ket=b.cursor,!b.in_grouping(m,97,249)))&&(b.slice_from(r),b.cursor=n,!0)}function _(e){if(b.cursor=e,!b.in_grouping(m,97,249))return!1;for(;!b.out_grouping(m,97,249);){if(b.cursor>=b.limit)return!1;b.cursor++}return!0}function g(){var e,r=b.cursor;if(!function(){if(b.in_grouping(m,97,249)){var e=b.cursor;if(b.out_grouping(m,97,249)){for(;!b.in_grouping(m,97,249);){if(b.cursor>=b.limit)return _(e);b.cursor++}return!0}return _(e)}return!1}()){if(b.cursor=r,!b.out_grouping(m,97,249))return;if(e=b.cursor,b.out_grouping(m,97,249)){for(;!b.in_grouping(m,97,249);){if(b.cursor>=b.limit)return b.cursor=e,void(b.in_grouping(m,97,249)&&b.cursor=b.limit)return;b.cursor++}s=b.cursor}function p(){for(;!b.in_grouping(m,97,249);){if(b.cursor>=b.limit)return!1;b.cursor++}for(;!b.out_grouping(m,97,249);){if(b.cursor>=b.limit)return!1;b.cursor++}return!0}function k(){return s<=b.cursor}function h(){return o<=b.cursor}function q(){var e;if(b.ket=b.cursor,!(e=b.find_among_b(i,51)))return!1;switch(b.bra=b.cursor,e){case 1:if(!h())return!1;b.slice_del();break;case 2:if(!h())return!1;b.slice_del(),b.ket=b.cursor,b.eq_s_b(2,"ic")&&(b.bra=b.cursor,h()&&b.slice_del());break;case 3:if(!h())return!1;b.slice_from("log");break;case 4:if(!h())return!1;b.slice_from("u");break;case 5:if(!h())return!1;b.slice_from("ente");break;case 6:if(!k())return!1;b.slice_del();break;case 7:if(!(t<=b.cursor))return!1;b.slice_del(),b.ket=b.cursor,(e=b.find_among_b(r,4))&&(b.bra=b.cursor,h()&&(b.slice_del(),1==e&&(b.ket=b.cursor,b.eq_s_b(2,"at")&&(b.bra=b.cursor,h()&&b.slice_del()))));break;case 8:if(!h())return!1;b.slice_del(),b.ket=b.cursor,(e=b.find_among_b(n,3))&&(b.bra=b.cursor,1==e&&h()&&b.slice_del());break;case 9:if(!h())return!1;b.slice_del(),b.ket=b.cursor,b.eq_s_b(2,"at")&&(b.bra=b.cursor,h()&&(b.slice_del(),b.ket=b.cursor,b.eq_s_b(2,"ic")&&(b.bra=b.cursor,h()&&b.slice_del())))}return!0}function C(){var e;e=b.limit-b.cursor,b.ket=b.cursor,b.in_grouping_b(f,97,242)&&(b.bra=b.cursor,k()&&(b.slice_del(),b.ket=b.cursor,b.eq_s_b(1,"i")&&(b.bra=b.cursor,k())))?b.slice_del():b.cursor=b.limit-e,b.ket=b.cursor,b.eq_s_b(1,"h")&&(b.bra=b.cursor,b.in_grouping_b(v,99,103)&&k()&&b.slice_del())}this.setCurrent=function(e){b.setCurrent(e)},this.getCurrent=function(){return b.getCurrent()},this.stem=function(){var e,r,n,i=b.cursor;return function(){for(var e,r,n,i,o=b.cursor;;){if(b.bra=b.cursor,e=b.find_among(a,7))switch(b.ket=b.cursor,e){case 1:b.slice_from("à");continue;case 2:b.slice_from("è");continue;case 3:b.slice_from("ì");continue;case 4:b.slice_from("ò");continue;case 5:b.slice_from("ù");continue;case 6:b.slice_from("qU");continue;case 7:if(b.cursor>=b.limit)break;b.cursor++;continue}break}for(b.cursor=o;;)for(r=b.cursor;;){if(n=b.cursor,b.in_grouping(m,97,249)){if(b.bra=b.cursor,i=b.cursor,d("u","U",n))break;if(b.cursor=i,d("i","I",n))break}if(b.cursor=n,b.cursor>=b.limit)return b.cursor=r;b.cursor++}}(),b.cursor=i,e=b.cursor,s=b.limit,o=t=s,g(),b.cursor=e,p()&&(t=b.cursor,p()&&(o=b.cursor)),b.limit_backward=i,b.cursor=b.limit,function(){var e;if(b.ket=b.cursor,b.find_among_b(c,37)&&(b.bra=b.cursor,(e=b.find_among_b(w,5))&&k()))switch(e){case 1:b.slice_del();break;case 2:b.slice_from("e")}}(),b.cursor=b.limit,q()||(b.cursor=b.limit,b.cursor>=s&&(n=b.limit_backward,b.limit_backward=s,b.ket=b.cursor,(r=b.find_among_b(l,87))&&(b.bra=b.cursor,1==r&&b.slice_del()),b.limit_backward=n)),b.cursor=b.limit,C(),b.cursor=b.limit_backward,function(){for(var e;b.bra=b.cursor,e=b.find_among(u,3);)switch(b.ket=b.cursor,e){case 1:b.slice_from("i");break;case 2:b.slice_from("u");break;case 3:if(b.cursor>=b.limit)return;b.cursor++}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.ja.js b/docs/build/html/_static/javascripts/lunr/lunr.ja.js deleted file mode 100644 index 69f620250..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.ja.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(m){if(void 0===m)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===m.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var l="2"==m.version[0];m.ja=function(){this.pipeline.reset(),this.pipeline.add(m.ja.trimmer,m.ja.stopWordFilter,m.ja.stemmer),l?this.tokenizer=m.ja.tokenizer:(m.tokenizer&&(m.tokenizer=m.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=m.ja.tokenizer))};var j=new m.TinySegmenter;m.ja.tokenizer=function(e){var r,t,i,n,o,s,p,a,u;if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return l?new m.Token(e.toLowerCase()):e.toLowerCase()});for(r=(t=e.toString().toLowerCase().replace(/^\s+/,"")).length-1;0<=r;r--)if(/\S/.test(t.charAt(r))){t=t.substring(0,r+1);break}for(o=[],i=t.length,p=a=0;a<=i;a++)if(s=a-p,t.charAt(a).match(/\s/)||a==i){if(0=_.limit||(_.cursor++,!1)}function w(){for(;!_.in_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}for(;!_.out_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}return!1}function b(){return i<=_.cursor}function p(){return e<=_.cursor}function g(){var r=_.limit-_.cursor;_.find_among_b(t,3)&&(_.cursor=_.limit-r,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del()))}function h(){var r;u=!1,_.ket=_.cursor,_.eq_s_b(1,"e")&&(_.bra=_.cursor,b()&&(r=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-r,_.slice_del(),u=!0,g())))}function k(){var r;b()&&(r=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-r,_.eq_s_b(3,"gem")||(_.cursor=_.limit-r,_.slice_del(),g())))}this.setCurrent=function(r){_.setCurrent(r)},this.getCurrent=function(){return _.getCurrent()},this.stem=function(){var r=_.cursor;return function(){for(var r,e,i,n=_.cursor;;){if(_.bra=_.cursor,r=_.find_among(o,11))switch(_.ket=_.cursor,r){case 1:_.slice_from("a");continue;case 2:_.slice_from("e");continue;case 3:_.slice_from("i");continue;case 4:_.slice_from("o");continue;case 5:_.slice_from("u");continue;case 6:if(_.cursor>=_.limit)break;_.cursor++;continue}break}for(_.cursor=n,_.bra=n,_.eq_s(1,"y")?(_.ket=_.cursor,_.slice_from("Y")):_.cursor=n;;)if(e=_.cursor,_.in_grouping(m,97,232)){if(i=_.cursor,_.bra=i,_.eq_s(1,"i"))_.ket=_.cursor,_.in_grouping(m,97,232)&&(_.slice_from("I"),_.cursor=e);else if(_.cursor=i,_.eq_s(1,"y"))_.ket=_.cursor,_.slice_from("Y"),_.cursor=e;else if(s(e))break}else if(s(e))break}(),_.cursor=r,i=_.limit,e=i,w()||((i=_.cursor)<3&&(i=3),w()||(e=_.cursor)),_.limit_backward=r,_.cursor=_.limit,function(){var r,e,i,n,o,t,s=_.limit-_.cursor;if(_.ket=_.cursor,r=_.find_among_b(c,5))switch(_.bra=_.cursor,r){case 1:b()&&_.slice_from("heid");break;case 2:k();break;case 3:b()&&_.out_grouping_b(f,97,232)&&_.slice_del()}if(_.cursor=_.limit-s,h(),_.cursor=_.limit-s,_.ket=_.cursor,_.eq_s_b(4,"heid")&&(_.bra=_.cursor,p()&&(e=_.limit-_.cursor,_.eq_s_b(1,"c")||(_.cursor=_.limit-e,_.slice_del(),_.ket=_.cursor,_.eq_s_b(2,"en")&&(_.bra=_.cursor,k())))),_.cursor=_.limit-s,_.ket=_.cursor,r=_.find_among_b(a,6))switch(_.bra=_.cursor,r){case 1:if(p()){if(_.slice_del(),i=_.limit-_.cursor,_.ket=_.cursor,_.eq_s_b(2,"ig")&&(_.bra=_.cursor,p()&&(n=_.limit-_.cursor,!_.eq_s_b(1,"e")))){_.cursor=_.limit-n,_.slice_del();break}_.cursor=_.limit-i,g()}break;case 2:p()&&(o=_.limit-_.cursor,_.eq_s_b(1,"e")||(_.cursor=_.limit-o,_.slice_del()));break;case 3:p()&&(_.slice_del(),h());break;case 4:p()&&_.slice_del();break;case 5:p()&&u&&_.slice_del()}_.cursor=_.limit-s,_.out_grouping_b(d,73,232)&&(t=_.limit-_.cursor,_.find_among_b(l,4)&&_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-t,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del())))}(),_.cursor=_.limit_backward,function(){for(var r;;)if(_.bra=_.cursor,r=_.find_among(n,3))switch(_.ket=_.cursor,r){case 1:_.slice_from("y");break;case 2:_.slice_from("i");break;case 3:if(_.cursor>=_.limit)return;_.cursor++}}(),!0}},function(r){return"function"==typeof r.update?r.update(function(r){return e.setCurrent(r),e.stem(),e.getCurrent()}):(e.setCurrent(r),e.stem(),e.getCurrent())}),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.no.js b/docs/build/html/_static/javascripts/lunr/lunr.no.js deleted file mode 100644 index 3d156b9c1..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.no.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,n,i;e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=(r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){var o,s,a=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],m=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],u=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],d=[119,125,149,1],c=new n;this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var e,r,n,i,t=c.cursor;return function(){var e,r=c.cursor+3;if(s=c.limit,0<=r||r<=c.limit){for(o=r;;){if(e=c.cursor,c.in_grouping(u,97,248)){c.cursor=e;break}if(e>=c.limit)return;c.cursor=e+1}for(;!c.out_grouping(u,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(s=c.cursor)=s&&(r=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,e=c.find_among_b(a,29),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:n=c.limit-c.cursor,c.in_grouping_b(d,98,122)?c.slice_del():(c.cursor=c.limit-n,c.eq_s_b(1,"k")&&c.out_grouping_b(u,97,248)&&c.slice_del());break;case 3:c.slice_from("er")}}(),c.cursor=c.limit,r=c.limit-c.cursor,c.cursor>=s&&(e=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,c.find_among_b(m,2)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e),c.cursor=c.limit,c.cursor>=s&&(i=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,(n=c.find_among_b(l,11))?(c.bra=c.cursor,c.limit_backward=i,1==n&&c.slice_del()):c.limit_backward=i),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.pt.js b/docs/build/html/_static/javascripts/lunr/lunr.pt.js deleted file mode 100644 index f50fc9fa6..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.pt.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var j,C,r;e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=(j=e.stemmerSupport.Among,C=e.stemmerSupport.SnowballProgram,r=new function(){var s,n,i,o=[new j("",-1,3),new j("ã",0,1),new j("õ",0,2)],a=[new j("",-1,3),new j("a~",0,1),new j("o~",0,2)],r=[new j("ic",-1,-1),new j("ad",-1,-1),new j("os",-1,-1),new j("iv",-1,1)],t=[new j("ante",-1,1),new j("avel",-1,1),new j("ível",-1,1)],u=[new j("ic",-1,1),new j("abil",-1,1),new j("iv",-1,1)],w=[new j("ica",-1,1),new j("ância",-1,1),new j("ência",-1,4),new j("ira",-1,9),new j("adora",-1,1),new j("osa",-1,1),new j("ista",-1,1),new j("iva",-1,8),new j("eza",-1,1),new j("logía",-1,2),new j("idade",-1,7),new j("ante",-1,1),new j("mente",-1,6),new j("amente",12,5),new j("ável",-1,1),new j("ível",-1,1),new j("ución",-1,3),new j("ico",-1,1),new j("ismo",-1,1),new j("oso",-1,1),new j("amento",-1,1),new j("imento",-1,1),new j("ivo",-1,8),new j("aça~o",-1,1),new j("ador",-1,1),new j("icas",-1,1),new j("ências",-1,4),new j("iras",-1,9),new j("adoras",-1,1),new j("osas",-1,1),new j("istas",-1,1),new j("ivas",-1,8),new j("ezas",-1,1),new j("logías",-1,2),new j("idades",-1,7),new j("uciones",-1,3),new j("adores",-1,1),new j("antes",-1,1),new j("aço~es",-1,1),new j("icos",-1,1),new j("ismos",-1,1),new j("osos",-1,1),new j("amentos",-1,1),new j("imentos",-1,1),new j("ivos",-1,8)],m=[new j("ada",-1,1),new j("ida",-1,1),new j("ia",-1,1),new j("aria",2,1),new j("eria",2,1),new j("iria",2,1),new j("ara",-1,1),new j("era",-1,1),new j("ira",-1,1),new j("ava",-1,1),new j("asse",-1,1),new j("esse",-1,1),new j("isse",-1,1),new j("aste",-1,1),new j("este",-1,1),new j("iste",-1,1),new j("ei",-1,1),new j("arei",16,1),new j("erei",16,1),new j("irei",16,1),new j("am",-1,1),new j("iam",20,1),new j("ariam",21,1),new j("eriam",21,1),new j("iriam",21,1),new j("aram",20,1),new j("eram",20,1),new j("iram",20,1),new j("avam",20,1),new j("em",-1,1),new j("arem",29,1),new j("erem",29,1),new j("irem",29,1),new j("assem",29,1),new j("essem",29,1),new j("issem",29,1),new j("ado",-1,1),new j("ido",-1,1),new j("ando",-1,1),new j("endo",-1,1),new j("indo",-1,1),new j("ara~o",-1,1),new j("era~o",-1,1),new j("ira~o",-1,1),new j("ar",-1,1),new j("er",-1,1),new j("ir",-1,1),new j("as",-1,1),new j("adas",47,1),new j("idas",47,1),new j("ias",47,1),new j("arias",50,1),new j("erias",50,1),new j("irias",50,1),new j("aras",47,1),new j("eras",47,1),new j("iras",47,1),new j("avas",47,1),new j("es",-1,1),new j("ardes",58,1),new j("erdes",58,1),new j("irdes",58,1),new j("ares",58,1),new j("eres",58,1),new j("ires",58,1),new j("asses",58,1),new j("esses",58,1),new j("isses",58,1),new j("astes",58,1),new j("estes",58,1),new j("istes",58,1),new j("is",-1,1),new j("ais",71,1),new j("eis",71,1),new j("areis",73,1),new j("ereis",73,1),new j("ireis",73,1),new j("áreis",73,1),new j("éreis",73,1),new j("íreis",73,1),new j("ásseis",73,1),new j("ésseis",73,1),new j("ísseis",73,1),new j("áveis",73,1),new j("íeis",73,1),new j("aríeis",84,1),new j("eríeis",84,1),new j("iríeis",84,1),new j("ados",-1,1),new j("idos",-1,1),new j("amos",-1,1),new j("áramos",90,1),new j("éramos",90,1),new j("íramos",90,1),new j("ávamos",90,1),new j("íamos",90,1),new j("aríamos",95,1),new j("eríamos",95,1),new j("iríamos",95,1),new j("emos",-1,1),new j("aremos",99,1),new j("eremos",99,1),new j("iremos",99,1),new j("ássemos",99,1),new j("êssemos",99,1),new j("íssemos",99,1),new j("imos",-1,1),new j("armos",-1,1),new j("ermos",-1,1),new j("irmos",-1,1),new j("ámos",-1,1),new j("arás",-1,1),new j("erás",-1,1),new j("irás",-1,1),new j("eu",-1,1),new j("iu",-1,1),new j("ou",-1,1),new j("ará",-1,1),new j("erá",-1,1),new j("irá",-1,1)],c=[new j("a",-1,1),new j("i",-1,1),new j("o",-1,1),new j("os",-1,1),new j("á",-1,1),new j("í",-1,1),new j("ó",-1,1)],l=[new j("e",-1,1),new j("ç",-1,2),new j("é",-1,1),new j("ê",-1,1)],f=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],d=new C;function v(){if(d.out_grouping(f,97,250)){for(;!d.in_grouping(f,97,250);){if(d.cursor>=d.limit)return!0;d.cursor++}return!1}return!0}function p(){var e,r,s=d.cursor;if(d.in_grouping(f,97,250))if(e=d.cursor,v()){if(d.cursor=e,function(){if(d.in_grouping(f,97,250))for(;!d.out_grouping(f,97,250);){if(d.cursor>=d.limit)return!1;d.cursor++}return i=d.cursor,!0}())return}else i=d.cursor;if(d.cursor=s,d.out_grouping(f,97,250)){if(r=d.cursor,v()){if(d.cursor=r,!d.in_grouping(f,97,250)||d.cursor>=d.limit)return;d.cursor++}i=d.cursor}}function _(){for(;!d.in_grouping(f,97,250);){if(d.cursor>=d.limit)return!1;d.cursor++}for(;!d.out_grouping(f,97,250);){if(d.cursor>=d.limit)return!1;d.cursor++}return!0}function h(){return i<=d.cursor}function b(){return s<=d.cursor}function g(){var e;if(d.ket=d.cursor,!(e=d.find_among_b(w,45)))return!1;switch(d.bra=d.cursor,e){case 1:if(!b())return!1;d.slice_del();break;case 2:if(!b())return!1;d.slice_from("log");break;case 3:if(!b())return!1;d.slice_from("u");break;case 4:if(!b())return!1;d.slice_from("ente");break;case 5:if(!(n<=d.cursor))return!1;d.slice_del(),d.ket=d.cursor,(e=d.find_among_b(r,4))&&(d.bra=d.cursor,b()&&(d.slice_del(),1==e&&(d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,b()&&d.slice_del()))));break;case 6:if(!b())return!1;d.slice_del(),d.ket=d.cursor,(e=d.find_among_b(t,3))&&(d.bra=d.cursor,1==e&&b()&&d.slice_del());break;case 7:if(!b())return!1;d.slice_del(),d.ket=d.cursor,(e=d.find_among_b(u,3))&&(d.bra=d.cursor,1==e&&b()&&d.slice_del());break;case 8:if(!b())return!1;d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,b()&&d.slice_del());break;case 9:if(!h()||!d.eq_s_b(1,"e"))return!1;d.slice_from("ir")}return!0}function k(e,r){if(d.eq_s_b(1,e)){d.bra=d.cursor;var s=d.limit-d.cursor;if(d.eq_s_b(1,r))return d.cursor=d.limit-s,h()&&d.slice_del(),!1}return!0}function q(){if(!g()&&(d.cursor=d.limit,!function(){var e,r;if(d.cursor>=i){if(r=d.limit_backward,d.limit_backward=i,d.ket=d.cursor,e=d.find_among_b(m,120))return d.bra=d.cursor,1==e&&d.slice_del(),d.limit_backward=r,!0;d.limit_backward=r}return!1}()))return d.cursor=d.limit,d.ket=d.cursor,void((e=d.find_among_b(c,7))&&(d.bra=d.cursor,1==e&&h()&&d.slice_del()));var e;d.cursor=d.limit,d.ket=d.cursor,d.eq_s_b(1,"i")&&(d.bra=d.cursor,d.eq_s_b(1,"c")&&(d.cursor=d.limit,h()&&d.slice_del()))}this.setCurrent=function(e){d.setCurrent(e)},this.getCurrent=function(){return d.getCurrent()},this.stem=function(){var e,r=d.cursor;return function(){for(var e;;){if(d.bra=d.cursor,e=d.find_among(o,3))switch(d.ket=d.cursor,e){case 1:d.slice_from("a~");continue;case 2:d.slice_from("o~");continue;case 3:if(d.cursor>=d.limit)break;d.cursor++;continue}break}}(),d.cursor=r,e=d.cursor,i=d.limit,s=n=i,p(),d.cursor=e,_()&&(n=d.cursor,_()&&(s=d.cursor)),d.limit_backward=r,d.cursor=d.limit,q(),d.cursor=d.limit,function(){var e;if(d.ket=d.cursor,e=d.find_among_b(l,4))switch(d.bra=d.cursor,e){case 1:h()&&(d.slice_del(),d.ket=d.cursor,d.limit,d.cursor,k("u","g")&&k("i","c"));break;case 2:d.slice_from("c")}}(),d.cursor=d.limit_backward,function(){for(var e;;){if(d.bra=d.cursor,e=d.find_among(a,3))switch(d.ket=d.cursor,e){case 1:d.slice_from("ã");continue;case 2:d.slice_from("õ");continue;case 3:if(d.cursor>=d.limit)break;d.cursor++;continue}break}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.ro.js b/docs/build/html/_static/javascripts/lunr/lunr.ro.js deleted file mode 100644 index b19627e1b..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.ro.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var h,z,i;e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=(h=e.stemmerSupport.Among,z=e.stemmerSupport.SnowballProgram,i=new function(){var r,n,t,a,o=[new h("",-1,3),new h("I",0,1),new h("U",0,2)],s=[new h("ea",-1,3),new h("aţia",-1,7),new h("aua",-1,2),new h("iua",-1,4),new h("aţie",-1,7),new h("ele",-1,3),new h("ile",-1,5),new h("iile",6,4),new h("iei",-1,4),new h("atei",-1,6),new h("ii",-1,4),new h("ului",-1,1),new h("ul",-1,1),new h("elor",-1,3),new h("ilor",-1,4),new h("iilor",14,4)],c=[new h("icala",-1,4),new h("iciva",-1,4),new h("ativa",-1,5),new h("itiva",-1,6),new h("icale",-1,4),new h("aţiune",-1,5),new h("iţiune",-1,6),new h("atoare",-1,5),new h("itoare",-1,6),new h("ătoare",-1,5),new h("icitate",-1,4),new h("abilitate",-1,1),new h("ibilitate",-1,2),new h("ivitate",-1,3),new h("icive",-1,4),new h("ative",-1,5),new h("itive",-1,6),new h("icali",-1,4),new h("atori",-1,5),new h("icatori",18,4),new h("itori",-1,6),new h("ători",-1,5),new h("icitati",-1,4),new h("abilitati",-1,1),new h("ivitati",-1,3),new h("icivi",-1,4),new h("ativi",-1,5),new h("itivi",-1,6),new h("icităi",-1,4),new h("abilităi",-1,1),new h("ivităi",-1,3),new h("icităţi",-1,4),new h("abilităţi",-1,1),new h("ivităţi",-1,3),new h("ical",-1,4),new h("ator",-1,5),new h("icator",35,4),new h("itor",-1,6),new h("ător",-1,5),new h("iciv",-1,4),new h("ativ",-1,5),new h("itiv",-1,6),new h("icală",-1,4),new h("icivă",-1,4),new h("ativă",-1,5),new h("itivă",-1,6)],u=[new h("ica",-1,1),new h("abila",-1,1),new h("ibila",-1,1),new h("oasa",-1,1),new h("ata",-1,1),new h("ita",-1,1),new h("anta",-1,1),new h("ista",-1,3),new h("uta",-1,1),new h("iva",-1,1),new h("ic",-1,1),new h("ice",-1,1),new h("abile",-1,1),new h("ibile",-1,1),new h("isme",-1,3),new h("iune",-1,2),new h("oase",-1,1),new h("ate",-1,1),new h("itate",17,1),new h("ite",-1,1),new h("ante",-1,1),new h("iste",-1,3),new h("ute",-1,1),new h("ive",-1,1),new h("ici",-1,1),new h("abili",-1,1),new h("ibili",-1,1),new h("iuni",-1,2),new h("atori",-1,1),new h("osi",-1,1),new h("ati",-1,1),new h("itati",30,1),new h("iti",-1,1),new h("anti",-1,1),new h("isti",-1,3),new h("uti",-1,1),new h("işti",-1,3),new h("ivi",-1,1),new h("ităi",-1,1),new h("oşi",-1,1),new h("ităţi",-1,1),new h("abil",-1,1),new h("ibil",-1,1),new h("ism",-1,3),new h("ator",-1,1),new h("os",-1,1),new h("at",-1,1),new h("it",-1,1),new h("ant",-1,1),new h("ist",-1,3),new h("ut",-1,1),new h("iv",-1,1),new h("ică",-1,1),new h("abilă",-1,1),new h("ibilă",-1,1),new h("oasă",-1,1),new h("ată",-1,1),new h("ită",-1,1),new h("antă",-1,1),new h("istă",-1,3),new h("ută",-1,1),new h("ivă",-1,1)],w=[new h("ea",-1,1),new h("ia",-1,1),new h("esc",-1,1),new h("ăsc",-1,1),new h("ind",-1,1),new h("ând",-1,1),new h("are",-1,1),new h("ere",-1,1),new h("ire",-1,1),new h("âre",-1,1),new h("se",-1,2),new h("ase",10,1),new h("sese",10,2),new h("ise",10,1),new h("use",10,1),new h("âse",10,1),new h("eşte",-1,1),new h("ăşte",-1,1),new h("eze",-1,1),new h("ai",-1,1),new h("eai",19,1),new h("iai",19,1),new h("sei",-1,2),new h("eşti",-1,1),new h("ăşti",-1,1),new h("ui",-1,1),new h("ezi",-1,1),new h("âi",-1,1),new h("aşi",-1,1),new h("seşi",-1,2),new h("aseşi",29,1),new h("seseşi",29,2),new h("iseşi",29,1),new h("useşi",29,1),new h("âseşi",29,1),new h("işi",-1,1),new h("uşi",-1,1),new h("âşi",-1,1),new h("aţi",-1,2),new h("eaţi",38,1),new h("iaţi",38,1),new h("eţi",-1,2),new h("iţi",-1,2),new h("âţi",-1,2),new h("arăţi",-1,1),new h("serăţi",-1,2),new h("aserăţi",45,1),new h("seserăţi",45,2),new h("iserăţi",45,1),new h("userăţi",45,1),new h("âserăţi",45,1),new h("irăţi",-1,1),new h("urăţi",-1,1),new h("ârăţi",-1,1),new h("am",-1,1),new h("eam",54,1),new h("iam",54,1),new h("em",-1,2),new h("asem",57,1),new h("sesem",57,2),new h("isem",57,1),new h("usem",57,1),new h("âsem",57,1),new h("im",-1,2),new h("âm",-1,2),new h("ăm",-1,2),new h("arăm",65,1),new h("serăm",65,2),new h("aserăm",67,1),new h("seserăm",67,2),new h("iserăm",67,1),new h("userăm",67,1),new h("âserăm",67,1),new h("irăm",65,1),new h("urăm",65,1),new h("ârăm",65,1),new h("au",-1,1),new h("eau",76,1),new h("iau",76,1),new h("indu",-1,1),new h("ându",-1,1),new h("ez",-1,1),new h("ească",-1,1),new h("ară",-1,1),new h("seră",-1,2),new h("aseră",84,1),new h("seseră",84,2),new h("iseră",84,1),new h("useră",84,1),new h("âseră",84,1),new h("iră",-1,1),new h("ură",-1,1),new h("âră",-1,1),new h("ează",-1,1)],i=[new h("a",-1,1),new h("e",-1,1),new h("ie",1,1),new h("i",-1,1),new h("ă",-1,1)],m=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],l=new z;function f(e,i){l.eq_s(1,e)&&(l.ket=l.cursor,l.in_grouping(m,97,259)&&l.slice_from(i))}function p(){if(l.out_grouping(m,97,259)){for(;!l.in_grouping(m,97,259);){if(l.cursor>=l.limit)return!0;l.cursor++}return!1}return!0}function d(){var e,i,r=l.cursor;if(l.in_grouping(m,97,259)){if(e=l.cursor,!p())return void(a=l.cursor);if(l.cursor=e,!function(){if(l.in_grouping(m,97,259))for(;!l.out_grouping(m,97,259);){if(l.cursor>=l.limit)return!0;l.cursor++}return!1}())return void(a=l.cursor)}l.cursor=r,l.out_grouping(m,97,259)&&(i=l.cursor,p()&&(l.cursor=i,l.in_grouping(m,97,259)&&l.cursor=l.limit)return!1;l.cursor++}for(;!l.out_grouping(m,97,259);){if(l.cursor>=l.limit)return!1;l.cursor++}return!0}function v(){return t<=l.cursor}function _(){var e,i=l.limit-l.cursor;if(l.ket=l.cursor,(e=l.find_among_b(c,46))&&(l.bra=l.cursor,v())){switch(e){case 1:l.slice_from("abil");break;case 2:l.slice_from("ibil");break;case 3:l.slice_from("iv");break;case 4:l.slice_from("ic");break;case 5:l.slice_from("at");break;case 6:l.slice_from("it")}return r=!0,l.cursor=l.limit-i,!0}return!1}function g(){var e,i;for(r=!1;;)if(i=l.limit-l.cursor,!_()){l.cursor=l.limit-i;break}if(l.ket=l.cursor,(e=l.find_among_b(u,62))&&(l.bra=l.cursor,n<=l.cursor)){switch(e){case 1:l.slice_del();break;case 2:l.eq_s_b(1,"ţ")&&(l.bra=l.cursor,l.slice_from("t"));break;case 3:l.slice_from("ist")}r=!0}}function k(){var e;l.ket=l.cursor,(e=l.find_among_b(i,5))&&(l.bra=l.cursor,a<=l.cursor&&1==e&&l.slice_del())}this.setCurrent=function(e){l.setCurrent(e)},this.getCurrent=function(){return l.getCurrent()},this.stem=function(){var e,i=l.cursor;return function(){for(var e,i;e=l.cursor,l.in_grouping(m,97,259)&&(i=l.cursor,l.bra=i,f("u","U"),l.cursor=i,f("i","I")),l.cursor=e,!(l.cursor>=l.limit);)l.cursor++}(),l.cursor=i,e=l.cursor,a=l.limit,n=t=a,d(),l.cursor=e,b()&&(t=l.cursor,b()&&(n=l.cursor)),l.limit_backward=i,l.cursor=l.limit,function(){var e,i;if(l.ket=l.cursor,(e=l.find_among_b(s,16))&&(l.bra=l.cursor,v()))switch(e){case 1:l.slice_del();break;case 2:l.slice_from("a");break;case 3:l.slice_from("e");break;case 4:l.slice_from("i");break;case 5:i=l.limit-l.cursor,l.eq_s_b(2,"ab")||(l.cursor=l.limit-i,l.slice_from("i"));break;case 6:l.slice_from("at");break;case 7:l.slice_from("aţi")}}(),l.cursor=l.limit,g(),l.cursor=l.limit,r||(l.cursor=l.limit,function(){var e,i,r;if(l.cursor>=a){if(i=l.limit_backward,l.limit_backward=a,l.ket=l.cursor,e=l.find_among_b(w,94))switch(l.bra=l.cursor,e){case 1:if(r=l.limit-l.cursor,!l.out_grouping_b(m,97,259)&&(l.cursor=l.limit-r,!l.eq_s_b(1,"u")))break;case 2:l.slice_del()}l.limit_backward=i}}(),l.cursor=l.limit),k(),l.cursor=l.limit_backward,function(){for(var e;;){if(l.bra=l.cursor,e=l.find_among(o,3))switch(l.ket=l.cursor,e){case 1:l.slice_from("i");continue;case 2:l.slice_from("u");continue;case 3:if(l.cursor>=l.limit)break;l.cursor++;continue}break}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.ru.js b/docs/build/html/_static/javascripts/lunr/lunr.ru.js deleted file mode 100644 index ac9924804..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.ru.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var h,g,n;e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=(h=e.stemmerSupport.Among,g=e.stemmerSupport.SnowballProgram,n=new function(){var n,e,r=[new h("в",-1,1),new h("ив",0,2),new h("ыв",0,2),new h("вши",-1,1),new h("ивши",3,2),new h("ывши",3,2),new h("вшись",-1,1),new h("ившись",6,2),new h("ывшись",6,2)],t=[new h("ее",-1,1),new h("ие",-1,1),new h("ое",-1,1),new h("ые",-1,1),new h("ими",-1,1),new h("ыми",-1,1),new h("ей",-1,1),new h("ий",-1,1),new h("ой",-1,1),new h("ый",-1,1),new h("ем",-1,1),new h("им",-1,1),new h("ом",-1,1),new h("ым",-1,1),new h("его",-1,1),new h("ого",-1,1),new h("ему",-1,1),new h("ому",-1,1),new h("их",-1,1),new h("ых",-1,1),new h("ею",-1,1),new h("ою",-1,1),new h("ую",-1,1),new h("юю",-1,1),new h("ая",-1,1),new h("яя",-1,1)],w=[new h("ем",-1,1),new h("нн",-1,1),new h("вш",-1,1),new h("ивш",2,2),new h("ывш",2,2),new h("щ",-1,1),new h("ющ",5,1),new h("ующ",6,2)],i=[new h("сь",-1,1),new h("ся",-1,1)],u=[new h("ла",-1,1),new h("ила",0,2),new h("ыла",0,2),new h("на",-1,1),new h("ена",3,2),new h("ете",-1,1),new h("ите",-1,2),new h("йте",-1,1),new h("ейте",7,2),new h("уйте",7,2),new h("ли",-1,1),new h("или",10,2),new h("ыли",10,2),new h("й",-1,1),new h("ей",13,2),new h("уй",13,2),new h("л",-1,1),new h("ил",16,2),new h("ыл",16,2),new h("ем",-1,1),new h("им",-1,2),new h("ым",-1,2),new h("н",-1,1),new h("ен",22,2),new h("ло",-1,1),new h("ило",24,2),new h("ыло",24,2),new h("но",-1,1),new h("ено",27,2),new h("нно",27,1),new h("ет",-1,1),new h("ует",30,2),new h("ит",-1,2),new h("ыт",-1,2),new h("ют",-1,1),new h("уют",34,2),new h("ят",-1,2),new h("ны",-1,1),new h("ены",37,2),new h("ть",-1,1),new h("ить",39,2),new h("ыть",39,2),new h("ешь",-1,1),new h("ишь",-1,2),new h("ю",-1,2),new h("ую",44,2)],s=[new h("а",-1,1),new h("ев",-1,1),new h("ов",-1,1),new h("е",-1,1),new h("ие",3,1),new h("ье",3,1),new h("и",-1,1),new h("еи",6,1),new h("ии",6,1),new h("ами",6,1),new h("ями",6,1),new h("иями",10,1),new h("й",-1,1),new h("ей",12,1),new h("ией",13,1),new h("ий",12,1),new h("ой",12,1),new h("ам",-1,1),new h("ем",-1,1),new h("ием",18,1),new h("ом",-1,1),new h("ям",-1,1),new h("иям",21,1),new h("о",-1,1),new h("у",-1,1),new h("ах",-1,1),new h("ях",-1,1),new h("иях",26,1),new h("ы",-1,1),new h("ь",-1,1),new h("ю",-1,1),new h("ию",30,1),new h("ью",30,1),new h("я",-1,1),new h("ия",33,1),new h("ья",33,1)],o=[new h("ост",-1,1),new h("ость",-1,1)],c=[new h("ейше",-1,1),new h("н",-1,2),new h("ейш",-1,1),new h("ь",-1,3)],m=[33,65,8,232],l=new g;function f(){for(;!l.in_grouping(m,1072,1103);){if(l.cursor>=l.limit)return!1;l.cursor++}return!0}function a(){for(;!l.out_grouping(m,1072,1103);){if(l.cursor>=l.limit)return!1;l.cursor++}return!0}function p(e,n){var r,t;if(l.ket=l.cursor,r=l.find_among_b(e,n)){switch(l.bra=l.cursor,r){case 1:if(t=l.limit-l.cursor,!l.eq_s_b(1,"а")&&(l.cursor=l.limit-t,!l.eq_s_b(1,"я")))return!1;case 2:l.slice_del()}return!0}return!1}function d(e,n){var r;return l.ket=l.cursor,!!(r=l.find_among_b(e,n))&&(l.bra=l.cursor,1==r&&l.slice_del(),!0)}function _(){return!!d(t,26)&&(p(w,8),!0)}function b(){var e;l.ket=l.cursor,(e=l.find_among_b(o,2))&&(l.bra=l.cursor,n<=l.cursor&&1==e&&l.slice_del())}this.setCurrent=function(e){l.setCurrent(e)},this.getCurrent=function(){return l.getCurrent()},this.stem=function(){return e=l.limit,n=e,f()&&(e=l.cursor,a()&&f()&&a()&&(n=l.cursor)),l.cursor=l.limit,!(l.cursor>3]&1<<(7&s))return this.cursor++,!0}return!1},in_grouping_b:function(r,t,i){if(this.cursor>this.limit_backward){var s=b.charCodeAt(this.cursor-1);if(s<=i&&t<=s&&r[(s-=t)>>3]&1<<(7&s))return this.cursor--,!0}return!1},out_grouping:function(r,t,i){if(this.cursor>3]&1<<(7&s)))return this.cursor++,!0}return!1},out_grouping_b:function(r,t,i){if(this.cursor>this.limit_backward){var s=b.charCodeAt(this.cursor-1);if(i>3]&1<<(7&s)))return this.cursor--,!0}return!1},eq_s:function(r,t){if(this.limit-this.cursor>1),a=0,f=u=(l=r[i]).s_size){if(this.cursor=e+l.s_size,!l.method)return l.result;var m=l.method();if(this.cursor=e+l.s_size,m)return l.result}if((i=l.substring_i)<0)return 0}},find_among_b:function(r,t){for(var i=0,s=t,e=this.cursor,n=this.limit_backward,u=0,o=0,h=!1;;){for(var c=i+(s-i>>1),a=0,f=u=(_=r[i]).s_size){if(this.cursor=e-_.s_size,!_.method)return _.result;var m=_.method();if(this.cursor=e-_.s_size,m)return _.result}if((i=_.substring_i)<0)return 0}},replace_s:function(r,t,i){var s=i.length-(t-r);return b=b.substring(0,r)+i+b.substring(t),this.limit+=s,this.cursor>=t?this.cursor+=s:this.cursor>r&&(this.cursor=r),s},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>b.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),b.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.sv.js b/docs/build/html/_static/javascripts/lunr/lunr.sv.js deleted file mode 100644 index 6daf5f9d8..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.sv.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,l,n;e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=(r=e.stemmerSupport.Among,l=e.stemmerSupport.SnowballProgram,n=new function(){var n,t,i=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],s=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],o=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],u=[119,127,149],m=new l;this.setCurrent=function(e){m.setCurrent(e)},this.getCurrent=function(){return m.getCurrent()},this.stem=function(){var e,r=m.cursor;return function(){var e,r=m.cursor+3;if(t=m.limit,0<=r||r<=m.limit){for(n=r;;){if(e=m.cursor,m.in_grouping(o,97,246)){m.cursor=e;break}if(m.cursor=e,m.cursor>=m.limit)return;m.cursor++}for(;!m.out_grouping(o,97,246);){if(m.cursor>=m.limit)return;m.cursor++}(t=m.cursor)=t&&(m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(i,37),m.limit_backward=r,e))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.in_grouping_b(u,98,121)&&m.slice_del()}}(),m.cursor=m.limit,e=m.limit_backward,m.cursor>=t&&(m.limit_backward=t,m.cursor=m.limit,m.find_among_b(s,7)&&(m.cursor=m.limit,m.ket=m.cursor,m.cursor>m.limit_backward&&(m.bra=--m.cursor,m.slice_del())),m.limit_backward=e),m.cursor=m.limit,function(){var e,r;if(m.cursor>=t){if(r=m.limit_backward,m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(a,5))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.slice_from("lös");break;case 3:m.slice_from("full")}m.limit_backward=r}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.th.js b/docs/build/html/_static/javascripts/lunr/lunr.th.js deleted file mode 100644 index ee8ef373a..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.th.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(t){if(void 0===t)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===t.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==t.version[0];t.th=function(){this.pipeline.reset(),this.pipeline.add(t.th.trimmer),i?this.tokenizer=t.th.tokenizer:(t.tokenizer&&(t.tokenizer=t.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=t.th.tokenizer))},t.th.wordCharacters="[฀-๿]",t.th.trimmer=t.trimmerSupport.generateTrimmer(t.th.wordCharacters),t.Pipeline.registerFunction(t.th.trimmer,"trimmer-th");var n=t.wordcut;n.init(),t.th.tokenizer=function(e){if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return i?new t.Token(e):e});var r=e.toString().replace(/^\s+/,"");return n.cut(r).split("|")}}}); \ No newline at end of file diff --git a/docs/build/html/_static/javascripts/lunr/lunr.tr.js b/docs/build/html/_static/javascripts/lunr/lunr.tr.js deleted file mode 100644 index e8fb5a7df..000000000 --- a/docs/build/html/_static/javascripts/lunr/lunr.tr.js +++ /dev/null @@ -1 +0,0 @@ -!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var mr,dr,i;r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=(mr=r.stemmerSupport.Among,dr=r.stemmerSupport.SnowballProgram,i=new function(){var t,r=[new mr("m",-1,-1),new mr("n",-1,-1),new mr("miz",-1,-1),new mr("niz",-1,-1),new mr("muz",-1,-1),new mr("nuz",-1,-1),new mr("müz",-1,-1),new mr("nüz",-1,-1),new mr("mız",-1,-1),new mr("nız",-1,-1)],i=[new mr("leri",-1,-1),new mr("ları",-1,-1)],e=[new mr("ni",-1,-1),new mr("nu",-1,-1),new mr("nü",-1,-1),new mr("nı",-1,-1)],n=[new mr("in",-1,-1),new mr("un",-1,-1),new mr("ün",-1,-1),new mr("ın",-1,-1)],u=[new mr("a",-1,-1),new mr("e",-1,-1)],o=[new mr("na",-1,-1),new mr("ne",-1,-1)],s=[new mr("da",-1,-1),new mr("ta",-1,-1),new mr("de",-1,-1),new mr("te",-1,-1)],c=[new mr("nda",-1,-1),new mr("nde",-1,-1)],l=[new mr("dan",-1,-1),new mr("tan",-1,-1),new mr("den",-1,-1),new mr("ten",-1,-1)],a=[new mr("ndan",-1,-1),new mr("nden",-1,-1)],m=[new mr("la",-1,-1),new mr("le",-1,-1)],d=[new mr("ca",-1,-1),new mr("ce",-1,-1)],f=[new mr("im",-1,-1),new mr("um",-1,-1),new mr("üm",-1,-1),new mr("ım",-1,-1)],b=[new mr("sin",-1,-1),new mr("sun",-1,-1),new mr("sün",-1,-1),new mr("sın",-1,-1)],w=[new mr("iz",-1,-1),new mr("uz",-1,-1),new mr("üz",-1,-1),new mr("ız",-1,-1)],_=[new mr("siniz",-1,-1),new mr("sunuz",-1,-1),new mr("sünüz",-1,-1),new mr("sınız",-1,-1)],k=[new mr("lar",-1,-1),new mr("ler",-1,-1)],p=[new mr("niz",-1,-1),new mr("nuz",-1,-1),new mr("nüz",-1,-1),new mr("nız",-1,-1)],g=[new mr("dir",-1,-1),new mr("tir",-1,-1),new mr("dur",-1,-1),new mr("tur",-1,-1),new mr("dür",-1,-1),new mr("tür",-1,-1),new mr("dır",-1,-1),new mr("tır",-1,-1)],y=[new mr("casına",-1,-1),new mr("cesine",-1,-1)],z=[new mr("di",-1,-1),new mr("ti",-1,-1),new mr("dik",-1,-1),new mr("tik",-1,-1),new mr("duk",-1,-1),new mr("tuk",-1,-1),new mr("dük",-1,-1),new mr("tük",-1,-1),new mr("dık",-1,-1),new mr("tık",-1,-1),new mr("dim",-1,-1),new mr("tim",-1,-1),new mr("dum",-1,-1),new mr("tum",-1,-1),new mr("düm",-1,-1),new mr("tüm",-1,-1),new mr("dım",-1,-1),new mr("tım",-1,-1),new mr("din",-1,-1),new mr("tin",-1,-1),new mr("dun",-1,-1),new mr("tun",-1,-1),new mr("dün",-1,-1),new mr("tün",-1,-1),new mr("dın",-1,-1),new mr("tın",-1,-1),new mr("du",-1,-1),new mr("tu",-1,-1),new mr("dü",-1,-1),new mr("tü",-1,-1),new mr("dı",-1,-1),new mr("tı",-1,-1)],h=[new mr("sa",-1,-1),new mr("se",-1,-1),new mr("sak",-1,-1),new mr("sek",-1,-1),new mr("sam",-1,-1),new mr("sem",-1,-1),new mr("san",-1,-1),new mr("sen",-1,-1)],v=[new mr("miş",-1,-1),new mr("muş",-1,-1),new mr("müş",-1,-1),new mr("mış",-1,-1)],q=[new mr("b",-1,1),new mr("c",-1,2),new mr("d",-1,3),new mr("ğ",-1,4)],C=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],P=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],F=[65],S=[65],W=[["a",[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],97,305],["e",[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],101,252],["ı",[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],97,305],["i",[17],101,105],["o",F,111,117],["ö",S,246,252],["u",F,111,117]],L=new dr;function x(r,i,e){for(;;){var n=L.limit-L.cursor;if(L.in_grouping_b(r,i,e)){L.cursor=L.limit-n;break}if(L.cursor=L.limit-n,L.cursor<=L.limit_backward)return!1;L.cursor--}return!0}function A(){var r,i;r=L.limit-L.cursor,x(C,97,305);for(var e=0;eL.limit_backward&&(L.cursor--,e=L.limit-L.cursor,i()))?(L.cursor=L.limit-e,!0):(L.cursor=L.limit-n,r()?(L.cursor=L.limit-n,!1):(L.cursor=L.limit-n,!(L.cursor<=L.limit_backward)&&(L.cursor--,!!i()&&(L.cursor=L.limit-n,!0))))}function j(r){return E(r,function(){return L.in_grouping_b(C,97,305)})}function T(){return j(function(){return L.eq_s_b(1,"n")})}function Z(){return j(function(){return L.eq_s_b(1,"y")})}function B(){return L.find_among_b(r,10)&&E(function(){return L.in_grouping_b(P,105,305)},function(){return L.out_grouping_b(C,97,305)})}function D(){return A()&&L.in_grouping_b(P,105,305)&&j(function(){return L.eq_s_b(1,"s")})}function G(){return L.find_among_b(i,2)}function H(){return A()&&L.find_among_b(n,4)&&T()}function I(){return A()&&L.find_among_b(s,4)}function J(){return A()&&L.find_among_b(c,2)}function K(){return A()&&L.find_among_b(f,4)&&Z()}function M(){return A()&&L.find_among_b(b,4)}function N(){return A()&&L.find_among_b(w,4)&&Z()}function O(){return L.find_among_b(_,4)}function Q(){return A()&&L.find_among_b(k,2)}function R(){return A()&&L.find_among_b(g,8)}function U(){return A()&&L.find_among_b(z,32)&&Z()}function V(){return L.find_among_b(h,8)&&Z()}function X(){return A()&&L.find_among_b(v,4)&&Z()}function Y(){var r=L.limit-L.cursor;return!(X()||(L.cursor=L.limit-r,U()||(L.cursor=L.limit-r,V()||(L.cursor=L.limit-r,L.eq_s_b(3,"ken")&&Z()))))}function $(){if(L.find_among_b(y,2)){var r=L.limit-L.cursor;if(O()||(L.cursor=L.limit-r,Q()||(L.cursor=L.limit-r,K()||(L.cursor=L.limit-r,M()||(L.cursor=L.limit-r,N()||(L.cursor=L.limit-r))))),X())return!1}return!0}function rr(){if(!A()||!L.find_among_b(p,4))return!0;var r=L.limit-L.cursor;return!U()&&(L.cursor=L.limit-r,!V())}function ir(){var r,i,e,n=L.limit-L.cursor;if(L.ket=L.cursor,t=!0,Y()&&(L.cursor=L.limit-n,$()&&(L.cursor=L.limit-n,function(){if(Q()){L.bra=L.cursor,L.slice_del();var r=L.limit-L.cursor;return L.ket=L.cursor,R()||(L.cursor=L.limit-r,U()||(L.cursor=L.limit-r,V()||(L.cursor=L.limit-r,X()||(L.cursor=L.limit-r)))),t=!1}return!0}()&&(L.cursor=L.limit-n,rr()&&(L.cursor=L.limit-n,e=L.limit-L.cursor,!(O()||(L.cursor=L.limit-e,N()||(L.cursor=L.limit-e,M()||(L.cursor=L.limit-e,K()))))||(L.bra=L.cursor,L.slice_del(),i=L.limit-L.cursor,L.ket=L.cursor,X()||(L.cursor=L.limit-i),0)))))){if(L.cursor=L.limit-n,!R())return;L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,r=L.limit-L.cursor,O()||(L.cursor=L.limit-r,Q()||(L.cursor=L.limit-r,K()||(L.cursor=L.limit-r,M()||(L.cursor=L.limit-r,N()||(L.cursor=L.limit-r))))),X()||(L.cursor=L.limit-r)}L.bra=L.cursor,L.slice_del()}function er(){var r,i,e,n;if(L.ket=L.cursor,L.eq_s_b(2,"ki")){if(r=L.limit-L.cursor,I())return L.bra=L.cursor,L.slice_del(),i=L.limit-L.cursor,L.ket=L.cursor,Q()?(L.bra=L.cursor,L.slice_del(),er()):(L.cursor=L.limit-i,B()&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er()))),!0;if(L.cursor=L.limit-r,H()){if(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,e=L.limit-L.cursor,G())L.bra=L.cursor,L.slice_del();else{if(L.cursor=L.limit-e,L.ket=L.cursor,!B()&&(L.cursor=L.limit-e,!D()&&(L.cursor=L.limit-e,!er())))return!0;L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())}return!0}if(L.cursor=L.limit-r,J()){if(n=L.limit-L.cursor,G())L.bra=L.cursor,L.slice_del();else if(L.cursor=L.limit-n,D())L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er());else if(L.cursor=L.limit-n,!er())return!1;return!0}}return!1}function nr(r){if(L.ket=L.cursor,!J()&&(L.cursor=L.limit-r,!A()||!L.find_among_b(o,2)))return!1;var i=L.limit-L.cursor;if(G())L.bra=L.cursor,L.slice_del();else if(L.cursor=L.limit-i,D())L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er());else if(L.cursor=L.limit-i,!er())return!1;return!0}function tr(r){if(L.ket=L.cursor,!(A()&&L.find_among_b(a,2)||(L.cursor=L.limit-r,A()&&L.find_among_b(e,4))))return!1;var i=L.limit-L.cursor;return!(!D()&&(L.cursor=L.limit-i,!G()))&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er()),!0)}function ur(){var r,i=L.limit-L.cursor;return L.ket=L.cursor,!!(H()||(L.cursor=L.limit-i,A()&&L.find_among_b(m,2)&&Z()))&&(L.bra=L.cursor,L.slice_del(),r=L.limit-L.cursor,L.ket=L.cursor,!(!Q()||(L.bra=L.cursor,L.slice_del(),!er()))||(L.cursor=L.limit-r,L.ket=L.cursor,(B()||(L.cursor=L.limit-r,D()||(L.cursor=L.limit-r,er())))&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())),!0))}function or(){var r,i,e=L.limit-L.cursor;if(L.ket=L.cursor,!(I()||(L.cursor=L.limit-e,A()&&L.in_grouping_b(P,105,305)&&Z()||(L.cursor=L.limit-e,A()&&L.find_among_b(u,2)&&Z()))))return!1;if(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,r=L.limit-L.cursor,B())L.bra=L.cursor,L.slice_del(),i=L.limit-L.cursor,L.ket=L.cursor,Q()||(L.cursor=L.limit-i);else if(L.cursor=L.limit-r,!Q())return!0;return L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,er(),!0}function sr(){var r,i,e=L.limit-L.cursor;if(L.ket=L.cursor,Q())return L.bra=L.cursor,L.slice_del(),void er();if(L.cursor=L.limit-e,L.ket=L.cursor,A()&&L.find_among_b(d,2)&&T())if(L.bra=L.cursor,L.slice_del(),r=L.limit-L.cursor,L.ket=L.cursor,G())L.bra=L.cursor,L.slice_del();else{if(L.cursor=L.limit-r,L.ket=L.cursor,!B()&&(L.cursor=L.limit-r,!D())){if(L.cursor=L.limit-r,L.ket=L.cursor,!Q())return;if(L.bra=L.cursor,L.slice_del(),!er())return}L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())}else if(L.cursor=L.limit-e,!nr(e)&&(L.cursor=L.limit-e,!tr(e))){if(L.cursor=L.limit-e,L.ket=L.cursor,A()&&L.find_among_b(l,4))return L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,i=L.limit-L.cursor,void(B()?(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())):(L.cursor=L.limit-i,Q()?(L.bra=L.cursor,L.slice_del()):L.cursor=L.limit-i,er()));if(L.cursor=L.limit-e,!ur()){if(L.cursor=L.limit-e,G())return L.bra=L.cursor,void L.slice_del();L.cursor=L.limit-e,er()||(L.cursor=L.limit-e,or()||(L.cursor=L.limit-e,L.ket=L.cursor,(B()||(L.cursor=L.limit-e,D()))&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er()))))}}}function cr(r,i,e){if(L.cursor=L.limit-r,function(){for(;;){var r=L.limit-L.cursor;if(L.in_grouping_b(C,97,305)){L.cursor=L.limit-r;break}if(L.cursor=L.limit-r,L.cursor<=L.limit_backward)return!1;L.cursor--}return!0}()){var n=L.limit-L.cursor;if(!L.eq_s_b(1,i)&&(L.cursor=L.limit-n,!L.eq_s_b(1,e)))return!0;L.cursor=L.limit-r;var t=L.cursor;return L.insert(L.cursor,L.cursor,e),L.cursor=t,!1}return!0}function lr(r,i,e){for(;!L.eq_s(i,e);){if(L.cursor>=L.limit)return!0;L.cursor++}return i!=L.limit||(L.cursor=r,!1)}function ar(){var r,i,e=L.cursor;return!(!lr(r=L.cursor,2,"ad")||!lr(L.cursor=r,5,"soyad"))&&(L.limit_backward=e,L.cursor=L.limit,i=L.limit-L.cursor,(L.eq_s_b(1,"d")||(L.cursor=L.limit-i,L.eq_s_b(1,"g")))&&cr(i,"a","ı")&&cr(i,"e","i")&&cr(i,"o","u")&&cr(i,"ö","ü"),L.cursor=L.limit,function(){var r;if(L.ket=L.cursor,r=L.find_among_b(q,4))switch(L.bra=L.cursor,r){case 1:L.slice_from("p");break;case 2:L.slice_from("ç");break;case 3:L.slice_from("t");break;case 4:L.slice_from("k")}}(),!0)}this.setCurrent=function(r){L.setCurrent(r)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){return!!(function(){for(var r,i=L.cursor,e=2;;){for(r=L.cursor;!L.in_grouping(C,97,305);){if(L.cursor>=L.limit)return L.cursor=r,!(0e&&(this._events[n].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[n].length),"function"==typeof console.trace&&console.trace()));return this},r.prototype.once=function(n,t){if(!a(t))throw TypeError("listener must be a function");var e=!1;function r(){this.removeListener(n,r),e||(e=!0,t.apply(this,arguments))}return r.listener=t,this.on(n,r),this},r.prototype.removeListener=function(n,t){var e,r,i,o;if(!a(t))throw TypeError("listener must be a function");if(!this._events||!this._events[n])return this;if(i=(e=this._events[n]).length,r=-1,e===t||a(e.listener)&&e.listener===t)delete this._events[n],this._events.removeListener&&this.emit("removeListener",n,t);else if(c(e)){for(o=i;0this.maxLength)return i();if(!this.stat&&p(this.cache,o)){var t=this.cache[o];if(Array.isArray(t)&&(t="DIR"),!n||"DIR"===t)return i(null,t);if(n&&"FILE"===t)return i()}var e=this.statCache[o];if(void 0!==e){if(!1===e)return i(null,e);var s=e.isDirectory()?"DIR":"FILE";return n&&"FILE"===s?i():i(null,s,e)}var a=this,c=d("stat\0"+o,function(n,e){{if(e&&e.isSymbolicLink())return u.stat(o,function(n,t){n?a._stat2(r,o,null,e,i):a._stat2(r,o,n,t,i)});a._stat2(r,o,n,e,i)}});c&&u.lstat(o,c)},b.prototype._stat2=function(n,t,e,r,i){if(e)return this.statCache[t]=!1,i();var o="/"===n.slice(-1);if(this.statCache[t]=r,"/"===t.slice(-1)&&!r.isDirectory())return i(null,!1,r);var s=r.isDirectory()?"DIR":"FILE";return this.cache[t]=this.cache[t]||s,o&&"DIR"!==s?i():i(null,s,r)}}).call(this,_("_process"))},{"./common.js":15,"./sync.js":17,_process:24,assert:9,events:14,fs:12,inflight:18,inherits:19,minimatch:20,once:21,path:22,"path-is-absolute":23,util:28}],17:[function(e,r,n){(function(i){(r.exports=n).GlobSync=h;var s=e("fs"),c=e("minimatch"),g=(c.Minimatch,e("./glob.js").Glob,e("util"),e("path")),u=e("assert"),l=e("path-is-absolute"),t=e("./common.js"),o=(t.alphasort,t.alphasorti,t.setopts),a=t.ownProp,f=t.childrenIgnored;function n(n,t){if("function"==typeof t||3===arguments.length)throw new TypeError("callback provided to sync glob\nSee: https://github.com/isaacs/node-glob/issues/167");return new h(n,t).found}function h(n,t){if(!n)throw new Error("must provide pattern");if("function"==typeof t||3===arguments.length)throw new TypeError("callback provided to sync glob\nSee: https://github.com/isaacs/node-glob/issues/167");if(!(this instanceof h))return new h(n,t);if(o(this,n,t),this.noprocess)return this;var e=this.minimatch.set.length;this.matches=new Array(e);for(var r=0;rthis.maxLength)return!1;if(!this.stat&&a(this.cache,t)){var r=this.cache[t];if(Array.isArray(r)&&(r="DIR"),!e||"DIR"===r)return r;if(e&&"FILE"===r)return!1}var i=this.statCache[t];if(!i){var o;try{o=s.lstatSync(t)}catch(n){return!1}if(o.isSymbolicLink())try{i=s.statSync(t)}catch(n){i=o}else i=o}r=(this.statCache[t]=i).isDirectory()?"DIR":"FILE";return this.cache[t]=this.cache[t]||r,(!e||"DIR"===r)&&r},h.prototype._mark=function(n){return t.mark(this,n)},h.prototype._makeAbs=function(n){return t.makeAbs(this,n)}}).call(this,e("_process"))},{"./common.js":15,"./glob.js":16,_process:24,assert:9,fs:12,minimatch:20,path:22,"path-is-absolute":23,util:28}],18:[function(t,r,n){(function(s){var n=t("wrappy"),a=Object.create(null),e=t("once");r.exports=n(function(n,t){return a[n]?(a[n].push(t),null):(a[n]=[t],o=n,e(function n(){var t=a[o],e=t.length,r=function(n){for(var t=n.length,e=[],r=0;re?(t.splice(0,e),s.nextTick(function(){n.apply(null,r)})):delete a[o]}}));var o})}).call(this,t("_process"))},{_process:24,once:21,wrappy:29}],19:[function(n,t,e){"function"==typeof Object.create?t.exports=function(n,t){n.super_=t,n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(n,t){n.super_=t;var e=function(){};e.prototype=t.prototype,n.prototype=new e,n.prototype.constructor=n}},{}],20:[function(n,t,e){(t.exports=s).Minimatch=i;var u={sep:"/"};try{u=n("path")}catch(n){}var M=s.GLOBSTAR=i.GLOBSTAR={},r=n("brace-expansion"),C={"!":{open:"(?:(?!(?:",close:"))[^/]*?)"},"?":{open:"(?:",close:")?"},"+":{open:"(?:",close:")+"},"*":{open:"(?:",close:")*"},"@":{open:"(?:",close:")"}},P="[^/]",z=P+"*?",B="().*{}+?[]^$\\!".split("").reduce(function(n,t){return n[t]=!0,n},{});var l=/\/+/;function o(t,e){t=t||{},e=e||{};var r={};return Object.keys(e).forEach(function(n){r[n]=e[n]}),Object.keys(t).forEach(function(n){r[n]=t[n]}),r}function s(n,t,e){if("string"!=typeof t)throw new TypeError("glob pattern string required");return e||(e={}),!(!e.nocomment&&"#"===t.charAt(0))&&(""===t.trim()?""===n:new i(t,e).match(n))}function i(n,t){if(!(this instanceof i))return new i(n,t);if("string"!=typeof n)throw new TypeError("glob pattern string required");t||(t={}),n=n.trim(),"/"!==u.sep&&(n=n.split(u.sep).join("/")),this.options=t,this.set=[],this.pattern=n,this.regexp=null,this.negate=!1,this.comment=!1,this.empty=!1,this.make()}function a(n,t){if(t||(t=this instanceof i?this.options:{}),void 0===(n=void 0===n?this.pattern:n))throw new TypeError("undefined pattern");return t.nobrace||!n.match(/\{.*\}/)?[n]:r(n)}s.filter=function(r,i){return i=i||{},function(n,t,e){return s(n,r,i)}},s.defaults=function(r){if(!r||!Object.keys(r).length)return s;var i=s,n=function(n,t,e){return i.minimatch(n,t,o(r,e))};return n.Minimatch=function(n,t){return new i.Minimatch(n,o(r,t))},n},i.defaults=function(n){return n&&Object.keys(n).length?s.defaults(n).Minimatch:i},i.prototype.debug=function(){},i.prototype.make=function(){if(this._made)return;var n=this.pattern,t=this.options;if(!t.nocomment&&"#"===n.charAt(0))return void(this.comment=!0);if(!n)return void(this.empty=!0);this.parseNegate();var e=this.globSet=this.braceExpand();t.debug&&(this.debug=console.error);this.debug(this.pattern,e),e=this.globParts=e.map(function(n){return n.split(l)}),this.debug(this.pattern,e),e=e.map(function(n,t,e){return n.map(this.parse,this)},this),this.debug(this.pattern,e),e=e.filter(function(n){return-1===n.indexOf(!1)}),this.debug(this.pattern,e),this.set=e},i.prototype.parseNegate=function(){var n=this.pattern,t=!1,e=this.options,r=0;if(e.nonegate)return;for(var i=0,o=n.length;i>> no match, partial?",n,f,t,h),f!==s))}if("string"==typeof u?(c=r.nocase?l.toLowerCase()===u.toLowerCase():l===u,this.debug("string match",u,l,c)):(c=l.match(u),this.debug("pattern match",u,l,c)),!c)return!1}if(i===s&&o===a)return!0;if(i===s)return e;if(o===a)return i===s-1&&""===n[i];throw new Error("wtf?")}},{"brace-expansion":11,path:22}],21:[function(n,t,e){var r=n("wrappy");function i(n){var t=function(){return t.called?t.value:(t.called=!0,t.value=n.apply(this,arguments))};return t.called=!1,t}function o(n){var t=function(){if(t.called)throw new Error(t.onceError);return t.called=!0,t.value=n.apply(this,arguments)},e=n.name||"Function wrapped with `once`";return t.onceError=e+" shouldn't be called more than once",t.called=!1,t}t.exports=r(i),t.exports.strict=r(o),i.proto=i(function(){Object.defineProperty(Function.prototype,"once",{value:function(){return i(this)},configurable:!0}),Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return o(this)},configurable:!0})})},{wrappy:29}],22:[function(n,t,u){(function(i){function o(n,t){for(var e=0,r=n.length-1;0<=r;r--){var i=n[r];"."===i?n.splice(r,1):".."===i?(n.splice(r,1),e++):e&&(n.splice(r,1),e--)}if(t)for(;e--;e)n.unshift("..");return n}var t=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,s=function(n){return t.exec(n).slice(1)};function a(n,t){if(n.filter)return n.filter(t);for(var e=[],r=0;r":">",'"':""","'":"'","`":"`"},D=d.invert(N),F=function(t){var e=function(n){return t[n]},n="(?:"+d.keys(t).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(n){return n=null==n?"":""+n,r.test(n)?n.replace(i,e):n}};d.escape=F(N),d.unescape=F(D),d.result=function(n,t,e){var r=null==n?void 0:n[t];return void 0===r&&(r=e),d.isFunction(r)?r.call(n):r};var M=0;d.uniqueId=function(n){var t=++M+"";return n?n+t:t},d.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var C=/(.)^/,P={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},z=/\\|'|\r|\n|\u2028|\u2029/g,B=function(n){return"\\"+P[n]};d.template=function(o,n,t){!n&&t&&(n=t),n=d.defaults({},n,d.templateSettings);var e=RegExp([(n.escape||C).source,(n.interpolate||C).source,(n.evaluate||C).source].join("|")+"|$","g"),s=0,a="__p+='";o.replace(e,function(n,t,e,r,i){return a+=o.slice(s,i).replace(z,B),s=i+n.length,t?a+="'+\n((__t=("+t+"))==null?'':_.escape(__t))+\n'":e?a+="'+\n((__t=("+e+"))==null?'':__t)+\n'":r&&(a+="';\n"+r+"\n__p+='"),n}),a+="';\n",n.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{var r=new Function(n.variable||"obj","_",a)}catch(n){throw n.source=a,n}var i=function(n){return r.call(this,n,d)},c=n.variable||"obj";return i.source="function("+c+"){\n"+a+"}",i},d.chain=function(n){var t=d(n);return t._chain=!0,t};var U=function(n,t){return n._chain?d(t).chain():t};d.mixin=function(e){d.each(d.functions(e),function(n){var t=d[n]=e[n];d.prototype[n]=function(){var n=[this._wrapped];return i.apply(n,arguments),U(this,t.apply(d,n))}})},d.mixin(d),d.each(["pop","push","reverse","shift","sort","splice","unshift"],function(t){var e=r[t];d.prototype[t]=function(){var n=this._wrapped;return e.apply(n,arguments),"shift"!==t&&"splice"!==t||0!==n.length||delete n[0],U(this,n)}}),d.each(["concat","join","slice"],function(n){var t=r[n];d.prototype[n]=function(){return U(this,t.apply(this._wrapped,arguments))}}),d.prototype.value=function(){return this._wrapped},d.prototype.valueOf=d.prototype.toJSON=d.prototype.value,d.prototype.toString=function(){return""+this._wrapped}}).call(this)},{}],26:[function(n,t,e){arguments[4][19][0].apply(e,arguments)},{dup:19}],27:[function(n,t,e){t.exports=function(n){return n&&"object"==typeof n&&"function"==typeof n.copy&&"function"==typeof n.fill&&"function"==typeof n.readUInt8}},{}],28:[function(h,n,k){(function(r,i){var a=/%[sdj%]/g;k.format=function(n){if(!_(n)){for(var t=[],e=0;e elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 - // Plus for old WebKit, typeof returns "function" for HTML collections - // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) - return typeof obj === "function" && typeof obj.nodeType !== "number" && - typeof obj.item !== "function"; - }; - - -var isWindow = function isWindow( obj ) { - return obj != null && obj === obj.window; - }; - - -var document = window.document; - - - - var preservedScriptAttributes = { - type: true, - src: true, - nonce: true, - noModule: true - }; - - function DOMEval( code, node, doc ) { - doc = doc || document; - - var i, val, - script = doc.createElement( "script" ); - - script.text = code; - if ( node ) { - for ( i in preservedScriptAttributes ) { - - // Support: Firefox 64+, Edge 18+ - // Some browsers don't support the "nonce" property on scripts. - // On the other hand, just using `getAttribute` is not enough as - // the `nonce` attribute is reset to an empty string whenever it - // becomes browsing-context connected. - // See https://github.com/whatwg/html/issues/2369 - // See https://html.spec.whatwg.org/#nonce-attributes - // The `node.getAttribute` check was added for the sake of - // `jQuery.globalEval` so that it can fake a nonce-containing node - // via an object. - val = node[ i ] || node.getAttribute && node.getAttribute( i ); - if ( val ) { - script.setAttribute( i, val ); - } - } - } - doc.head.appendChild( script ).parentNode.removeChild( script ); - } - - -function toType( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; -} -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.6.0", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); - } - - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - even: function() { - return this.pushStack( jQuery.grep( this, function( _elem, i ) { - return ( i + 1 ) % 2; - } ) ); - }, - - odd: function() { - return this.pushStack( jQuery.grep( this, function( _elem, i ) { - return i % 2; - } ) ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - copy = options[ name ]; - - // Prevent Object.prototype pollution - // Prevent never-ending loop - if ( name === "__proto__" || target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { - src = target[ name ]; - - // Ensure proper type for the source value - if ( copyIsArray && !Array.isArray( src ) ) { - clone = []; - } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { - clone = {}; - } else { - clone = src; - } - copyIsArray = false; - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - // Evaluates a script in a provided context; falls back to the global one - // if not specified. - globalEval: function( code, options, doc ) { - DOMEval( code, { nonce: options && options.nonce }, doc ); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return flat( ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), - function( _i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); - } ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = toType( obj ); - - if ( isFunction( obj ) || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.6 - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://js.foundation/ - * - * Date: 2021-02-16 - */ -( function( window ) { -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - nonnativeSelectorCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ( {} ).hasOwnProperty, - arr = [], - pop = arr.pop, - pushNative = arr.push, - push = arr.push, - slice = arr.slice, - - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[ i ] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + - "ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram - identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + - "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - - // "Attribute values must be CSS identifiers [capture 5] - // or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + - whitespace + "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + - whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + - "*" ), - rdescend = new RegExp( whitespace + "|>" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + - whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + - whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + - "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rhtml = /HTML$/i, - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), - funescape = function( escape, nonHex ) { - var high = "0x" + escape.slice( 1 ) - 0x10000; - - return nonHex ? - - // Strip the backslash prefix from a non-hex escape sequence - nonHex : - - // Replace a hexadecimal escape sequence with the encoded Unicode code point - // Support: IE <=11+ - // For values outside the Basic Multilingual Plane (BMP), manually construct a - // surrogate pair - high < 0 ? - String.fromCharCode( high + 0x10000 ) : - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + - ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - inDisabledFieldset = addCombinator( - function( elem ) { - return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - ( arr = slice.call( preferredDoc.childNodes ) ), - preferredDoc.childNodes - ); - - // Support: Android<4.0 - // Detect silently failing push.apply - // eslint-disable-next-line no-unused-expressions - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - pushNative.apply( target, slice.call( els ) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - - // Can't trust NodeList.length - while ( ( target[ j++ ] = els[ i++ ] ) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - setDocument( context ); - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { - - // ID selector - if ( ( m = match[ 1 ] ) ) { - - // Document context - if ( nodeType === 9 ) { - if ( ( elem = context.getElementById( m ) ) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && ( elem = newContext.getElementById( m ) ) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[ 2 ] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !nonnativeSelectorCache[ selector + " " ] && - ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && - - // Support: IE 8 only - // Exclude object elements - ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { - - newSelector = selector; - newContext = context; - - // qSA considers elements outside a scoping root when evaluating child or - // descendant combinators, which is not what we want. - // In such cases, we work around the behavior by prefixing every selector in the - // list with an ID selector referencing the scope context. - // The technique has to be used as well when a leading combinator is used - // as such selectors are not recognized by querySelectorAll. - // Thanks to Andrew Dupont for this technique. - if ( nodeType === 1 && - ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - - // We can use :scope instead of the ID hack if the browser - // supports it & if we're not changing the context. - if ( newContext !== context || !support.scope ) { - - // Capture the context ID, setting it first if necessary - if ( ( nid = context.getAttribute( "id" ) ) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", ( nid = expando ) ); - } - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + - toSelector( groups[ i ] ); - } - newSelector = groups.join( "," ); - } - - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - nonnativeSelectorCache( selector, true ); - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return ( cache[ key + " " ] = value ); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement( "fieldset" ); - - try { - return !!fn( el ); - } catch ( e ) { - return false; - } finally { - - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split( "|" ), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[ i ] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( ( cur = cur.nextSibling ) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return ( name === "input" || name === "button" ) && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - inDisabledFieldset( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction( function( argument ) { - argument = +argument; - return markFunction( function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ ( j = matchIndexes[ i ] ) ] ) { - seed[ j ] = !( matches[ j ] = seed[ j ] ); - } - } - } ); - } ); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - var namespace = elem && elem.namespaceURI, - docElem = elem && ( elem.ownerDocument || elem ).documentElement; - - // Support: IE <=8 - // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes - // https://bugs.jquery.com/ticket/4833 - return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9 - 11+, Edge 12 - 18+ - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( preferredDoc != document && - ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, - // Safari 4 - 5 only, Opera <=11.6 - 12.x only - // IE/Edge & older browsers don't support the :scope pseudo-class. - // Support: Safari 6.0 only - // Safari 6.0 supports :scope but it's an alias of :root there. - support.scope = assert( function( el ) { - docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); - return typeof el.querySelectorAll !== "undefined" && - !el.querySelectorAll( ":scope fieldset div" ).length; - } ); - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert( function( el ) { - el.className = "i"; - return !el.getAttribute( "className" ); - } ); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert( function( el ) { - el.appendChild( document.createComment( "" ) ); - return !el.getElementsByTagName( "*" ).length; - } ); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert( function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - } ); - - // ID filter and find - if ( support.getById ) { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute( "id" ) === attrId; - }; - }; - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode( "id" ); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( ( elem = elems[ i++ ] ) ) { - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find[ "TAG" ] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert( function( el ) { - - var input; - - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll( "[selected]" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push( "~=" ); - } - - // Support: IE 11+, Edge 15 - 18+ - // IE 11/Edge don't find elements on a `[name='']` query in some cases. - // Adding a temporary attribute to the document before the selection works - // around the issue. - // Interestingly, IE 10 & older don't seem to have the issue. - input = document.createElement( "input" ); - input.setAttribute( "name", "" ); - el.appendChild( input ); - if ( !el.querySelectorAll( "[name='']" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + - whitespace + "*(?:''|\"\")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll( ":checked" ).length ) { - rbuggyQSA.push( ":checked" ); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push( ".#.+[+~]" ); - } - - // Support: Firefox <=3.6 - 5 only - // Old Firefox doesn't throw on a badly-escaped identifier. - el.querySelectorAll( "\\\f" ); - rbuggyQSA.push( "[\\r\\n\\f]" ); - } ); - - assert( function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement( "input" ); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll( "[name=d]" ).length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: Opera 10 - 11 only - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll( "*,:x" ); - rbuggyQSA.push( ",.*:" ); - } ); - } - - if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector ) ) ) ) { - - assert( function( el ) { - - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - } ); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - ) ); - } : - function( a, b ) { - if ( b ) { - while ( ( b = b.parentNode ) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { - - // Choose the first element that is related to our preferred document - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( a == document || a.ownerDocument == preferredDoc && - contains( preferredDoc, a ) ) { - return -1; - } - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( b == document || b.ownerDocument == preferredDoc && - contains( preferredDoc, b ) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - return a == document ? -1 : - b == document ? 1 : - /* eslint-enable eqeqeq */ - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( ( cur = cur.parentNode ) ) { - ap.unshift( cur ); - } - cur = b; - while ( ( cur = cur.parentNode ) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[ i ] === bp[ i ] ) { - i++; - } - - return i ? - - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[ i ], bp[ i ] ) : - - // Otherwise nodes in our document sort first - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - ap[ i ] == preferredDoc ? -1 : - bp[ i ] == preferredDoc ? 1 : - /* eslint-enable eqeqeq */ - 0; - }; - - return document; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - setDocument( elem ); - - if ( support.matchesSelector && documentIsHTML && - !nonnativeSelectorCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch ( e ) { - nonnativeSelectorCache( expr, true ); - } - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - - // Set document vars if needed - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( ( context.ownerDocument || context ) != document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - - // Set document vars if needed - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( ( elem.ownerDocument || elem ) != document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - ( val = elem.getAttributeNode( name ) ) && val.specified ? - val.value : - null; -}; - -Sizzle.escape = function( sel ) { - return ( sel + "" ).replace( rcssescape, fcssescape ); -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - - // If no nodeType, this is expected to be an array - while ( ( node = elem[ i++ ] ) ) { - - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[ 1 ] = match[ 1 ].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[ 3 ] = ( match[ 3 ] || match[ 4 ] || - match[ 5 ] || "" ).replace( runescape, funescape ); - - if ( match[ 2 ] === "~=" ) { - match[ 3 ] = " " + match[ 3 ] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[ 1 ] = match[ 1 ].toLowerCase(); - - if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - - // nth-* requires argument - if ( !match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[ 4 ] = +( match[ 4 ] ? - match[ 5 ] + ( match[ 6 ] || 1 ) : - 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); - match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - - // other types prohibit arguments - } else if ( match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[ 6 ] && match[ 2 ]; - - if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[ 3 ] ) { - match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - - // Get excess from tokenize (recursively) - ( excess = tokenize( unquoted, true ) ) && - - // advance to the next closing parenthesis - ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { - - // excess is a negative index - match[ 0 ] = match[ 0 ].slice( 0, excess ); - match[ 2 ] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { - return true; - } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - ( pattern = new RegExp( "(^|" + whitespace + - ")" + className + "(" + whitespace + "|$)" ) ) && classCache( - className, function( elem ) { - return pattern.test( - typeof elem.className === "string" && elem.className || - typeof elem.getAttribute !== "undefined" && - elem.getAttribute( "class" ) || - "" - ); - } ); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - /* eslint-disable max-len */ - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - /* eslint-enable max-len */ - - }; - }, - - "CHILD": function( type, what, _argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, _context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( ( node = node[ dir ] ) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( ( node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - ( diff = nodeIndex = 0 ) || start.pop() ) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - - // Use previously-cached element index if available - if ( useCache ) { - - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - - // Use the same loop as above to seek `elem` from the start - while ( ( node = ++nodeIndex && node && node[ dir ] || - ( diff = nodeIndex = 0 ) || start.pop() ) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || - ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction( function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[ i ] ); - seed[ idx ] = !( matches[ idx ] = matched[ i ] ); - } - } ) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - - // Potentially complex pseudos - "not": markFunction( function( selector ) { - - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction( function( seed, matches, _context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( ( elem = unmatched[ i ] ) ) { - seed[ i ] = !( matches[ i ] = elem ); - } - } - } ) : - function( elem, _context, xml ) { - input[ 0 ] = elem; - matcher( input, null, xml, results ); - - // Don't keep the element (issue #299) - input[ 0 ] = null; - return !results.pop(); - }; - } ), - - "has": markFunction( function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - } ), - - "contains": markFunction( function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; - }; - } ), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - - // lang value must be a valid identifier - if ( !ridentifier.test( lang || "" ) ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( ( elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); - return false; - }; - } ), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && - ( !document.hasFocus || document.hasFocus() ) && - !!( elem.type || elem.href || ~elem.tabIndex ); - }, - - // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), - - "checked": function( elem ) { - - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return ( nodeName === "input" && !!elem.checked ) || - ( nodeName === "option" && !!elem.selected ); - }, - - "selected": function( elem ) { - - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - // eslint-disable-next-line no-unused-expressions - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos[ "empty" ]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( ( attr = elem.getAttribute( "type" ) ) == null || - attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo( function() { - return [ 0 ]; - } ), - - "last": createPositionalPseudo( function( _matchIndexes, length ) { - return [ length - 1 ]; - } ), - - "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - } ), - - "even": createPositionalPseudo( function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ), - - "odd": createPositionalPseudo( function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ), - - "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { - var i = argument < 0 ? - argument + length : - argument > length ? - length : - argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ), - - "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ) - } -}; - -Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || ( match = rcomma.exec( soFar ) ) ) { - if ( match ) { - - // Don't consume trailing commas as valid - soFar = soFar.slice( match[ 0 ].length ) || soFar; - } - groups.push( ( tokens = [] ) ); - } - - matched = false; - - // Combinators - if ( ( match = rcombinators.exec( soFar ) ) ) { - matched = match.shift(); - tokens.push( { - value: matched, - - // Cast descendant combinators to space - type: match[ 0 ].replace( rtrim, " " ) - } ); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || - ( match = preFilters[ type ]( match ) ) ) ) { - matched = match.shift(); - tokens.push( { - value: matched, - type: type, - matches: match - } ); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[ i ].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "parentNode", - doneName = done++; - - return combinator.first ? - - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - return false; - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || ( elem[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || - ( outerCache[ elem.uniqueID ] = {} ); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( ( oldCache = uniqueCache[ key ] ) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return ( newCache[ 2 ] = oldCache[ 2 ] ); - } else { - - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { - return true; - } - } - } - } - } - return false; - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[ i ]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[ 0 ]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[ i ], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( ( elem = unmatched[ i ] ) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction( function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( - selector || "*", - context.nodeType ? [ context ] : context, - [] - ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( ( elem = temp[ i ] ) ) { - matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( ( elem = matcherOut[ i ] ) ) { - - // Restore matcherIn since elem is not yet a final match - temp.push( ( matcherIn[ i ] = elem ) ); - } - } - postFinder( null, ( matcherOut = [] ), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( ( elem = matcherOut[ i ] ) && - ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { - - seed[ temp ] = !( results[ temp ] = elem ); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - } ); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[ 0 ].type ], - implicitRelative = leadingRelative || Expr.relative[ " " ], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - ( checkContext = context ).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[ j ].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens - .slice( 0, i - 1 ) - .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), - - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), - len = elems.length; - - if ( outermost ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - outermostContext = context == document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( !context && elem.ownerDocument != document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( ( matcher = elementMatchers[ j++ ] ) ) { - if ( matcher( elem, context || document, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - - // They will have gone through all possible matchers - if ( ( elem = !matcher && elem ) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( ( matcher = setMatchers[ j++ ] ) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !( unmatched[ i ] || setMatched[ i ] ) ) { - setMatched[ i ] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[ i ] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( - selector, - matcherFromGroupMatchers( elementMatchers, setMatchers ) - ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( ( selector = compiled.selector || selector ) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[ 0 ] = match[ 0 ].slice( 0 ); - if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { - - context = ( Expr.find[ "ID" ]( token.matches[ 0 ] - .replace( runescape, funescape ), context ) || [] )[ 0 ]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[ i ]; - - // Abort if we hit a combinator - if ( Expr.relative[ ( type = token.type ) ] ) { - break; - } - if ( ( find = Expr.find[ type ] ) ) { - - // Search, expanding context for leading sibling combinators - if ( ( seed = find( - token.matches[ 0 ].replace( runescape, funescape ), - rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || - context - ) ) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert( function( el ) { - - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; -} ); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert( function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute( "href" ) === "#"; -} ) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - } ); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert( function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -} ) ) { - addHandle( "value", function( elem, _name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - } ); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert( function( el ) { - return el.getAttribute( "disabled" ) == null; -} ) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - ( val = elem.getAttributeNode( name ) ) && val.specified ? - val.value : - null; - } - } ); -} - -return Sizzle; - -} )( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; - -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; - - - - -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; -}; - - -var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -} -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - - - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } - - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } - - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - // Filtered directly for both simple and complex selectors - return jQuery.filter( qualifier, elements, not ); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } - - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); -}; - -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - ret = this.pushStack( [] ); - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - if ( elem ) { - - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); - - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); - -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, _i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, _i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, _i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - if ( elem.contentDocument != null && - - // Support: IE 11+ - // elements with no `data` attribute has an object - // `contentDocument` with a `null` prototype. - getProto( elem.contentDocument ) ) { - - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - - - -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = locked || options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && toType( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -function Identity( v ) { - return v; -} -function Thrower( ex ) { - throw ex; -} - -function adoptValue( value, resolve, reject, noValue ) { - var method; - - try { - - // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); - - // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); - - // Other non-thenables - } else { - - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); - } - - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} - -jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, - - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( _i, tuple ) { - - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; - - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; - - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } - - returned = handler.apply( that, args ); - - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } - - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && - - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; - - // Handle a returned thenable - if ( isFunction( then ) ) { - - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); - - // Normal processors (resolve) also hook into progress - } else { - - // ...and disregard older resolution values - maxDepth++; - - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } - - // Handle all other returned values - } else { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } - - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, - - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { - - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } - - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } - - deferred.rejectWith( that, args ); - } - } - }; - - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { - - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } - - return jQuery.Deferred( function( newDefer ) { - - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); - - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); - - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; - - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( - function() { - - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, - - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, - - // rejected_handlers.disable - // fulfilled_handlers.disable - tuples[ 3 - i ][ 3 ].disable, - - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock, - - // progress_handlers.lock - tuples[ 0 ][ 3 ].lock - ); - } - - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); - - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; - - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( singleValue ) { - var - - // count of uncompleted subordinates - remaining = arguments.length, - - // count of unprocessed arguments - i = remaining, - - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), - - // the primary Deferred - primary = jQuery.Deferred(), - - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - primary.resolveWith( resolveContexts, resolveValues ); - } - }; - }; - - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, - !remaining ); - - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( primary.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - - return primary.then(); - } - } - - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); - } - - return primary.promise(); - } -} ); - - -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - -jQuery.Deferred.exceptionHook = function( error, stack ) { - - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; - - - - -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; - - - - -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); - -jQuery.fn.ready = function( fn ) { - - readyList - .then( fn ) - - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); - - return this; -}; - -jQuery.extend( { - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - } -} ); - -jQuery.ready.then = readyList.then; - -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} - -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - -} else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( toType( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, _key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - if ( chainable ) { - return elems; - } - - // Gets - if ( bulk ) { - return fn.call( elems ); - } - - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; - - -// Matches dashed string for camelizing -var rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g; - -// Used by camelCase as callback to replace() -function fcamelCase( _all, letter ) { - return letter.toUpperCase(); -} - -// Convert dashed to camelCase; used by the css and data modules -// Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) -function camelCase( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); -} -var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - - - -function Data() { - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; - -Data.prototype = { - - cache: function( owner ) { - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ camelCase( data ) ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; - }, - access: function( owner, key, value ) { - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - return this.get( owner, key ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key !== undefined ) { - - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { - - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( camelCase ); - } else { - key = camelCase( key ); - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } - - i = key.length; - - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - -function getData( data ) { - if ( data === "true" ) { - return true; - } - - if ( data === "false" ) { - return false; - } - - if ( data === "null" ) { - return null; - } - - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } - - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } - - return data; -} - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); - -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } -} ); - - -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); - -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var documentElement = document.documentElement; - - - - var isAttached = function( elem ) { - return jQuery.contains( elem.ownerDocument, elem ); - }, - composed = { composed: true }; - - // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only - // Check attachment across shadow DOM boundaries when possible (gh-3504) - // Support: iOS 10.0-10.2 only - // Early iOS 10 versions support `attachShadow` but not `getRootNode`, - // leading to errors. We need to check for `getRootNode`. - if ( documentElement.getRootNode ) { - isAttached = function( elem ) { - return jQuery.contains( elem.ownerDocument, elem ) || - elem.getRootNode( composed ) === elem.ownerDocument; - }; - } -var isHiddenWithinTree = function( elem, el ) { - - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - isAttached( elem ) && - - jQuery.css( elem, "display" ) === "none"; - }; - - - -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, scale, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = elem.nodeType && - ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Support: Firefox <=54 - // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) - initial = initial / 2; - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - while ( maxIterations-- ) { - - // Evaluate and update our best guess (doubling guesses that zero out). - // Finish if the scale equals or crosses 1 (making the old*new product non-positive). - jQuery.style( elem, prop, initialInUnit + unit ); - if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { - maxIterations = 0; - } - initialInUnit = initialInUnit / scale; - - } - - initialInUnit = initialInUnit * 2; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} - - -var defaultDisplayMap = {}; - -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; - - if ( display ) { - return display; - } - - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); - - temp.parentNode.removeChild( temp ); - - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; - - return display; -} - -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; - - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - display = elem.style.display; - if ( show ) { - - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; - } - } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); - } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); - } - } - } - - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } - - return elements; -} - -jQuery.fn.extend( { - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each( function() { - if ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); - -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); - -var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - - - -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - - // Support: IE <=9 only - // IE <=9 replaces "; - support.option = !!div.lastChild; -} )(); - - -// We have to close these tags to support XHTML (#13200) -var wrapMap = { - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] -}; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: IE <=9 only -if ( !support.option ) { - wrapMap.optgroup = wrapMap.option = [ 1, "" ]; -} - - -function getAll( context, tag ) { - - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; - - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); - - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); - - } else { - ret = []; - } - - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } - - return ret; -} - - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} - - -var rhtml = /<|&#?\w+;/; - -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, attached, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - attached = isAttached( elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( attached ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; -} - - -var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -// Support: IE <=9 - 11+ -// focus() and blur() are asynchronous, except when they are no-op. -// So expect focus to be synchronous when the element is already active, -// and blur to be synchronous when the element is not already active. -// (focus and blur are always synchronous in other supported browsers, -// this just defines when we can count on it). -function expectSync( elem, type ) { - return ( elem === safeActiveElement() ) === ( type === "focus" ); -} - -// Support: IE <=9 only -// Accessing document.activeElement can throw unexpectedly -// https://bugs.jquery.com/ticket/13393 -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Only attach events to objects that accept data - if ( !acceptData( elem ) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, selector ); - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = Object.create( null ); - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( nativeEvent ) { - - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( nativeEvent ), - - handlers = ( - dataPriv.get( this, "events" ) || Object.create( null ) - )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } - - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // If the event is namespaced, then each handler is only invoked if it is - // specially universal or its namespaces are a superset of the event's. - if ( !event.rnamespace || handleObj.namespace === false || - event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - if ( delegateCount && - - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, - - get: isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, - - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, - - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - click: { - - // Utilize native event to ensure correct state for checkable inputs - setup: function( data ) { - - // For mutual compressibility with _default, replace `this` access with a local var. - // `|| data` is dead code meant only to preserve the variable through minification. - var el = this || data; - - // Claim the first handler - if ( rcheckableType.test( el.type ) && - el.click && nodeName( el, "input" ) ) { - - // dataPriv.set( el, "click", ... ) - leverageNative( el, "click", returnTrue ); - } - - // Return false to allow normal processing in the caller - return false; - }, - trigger: function( data ) { - - // For mutual compressibility with _default, replace `this` access with a local var. - // `|| data` is dead code meant only to preserve the variable through minification. - var el = this || data; - - // Force setup before triggering a click - if ( rcheckableType.test( el.type ) && - el.click && nodeName( el, "input" ) ) { - - leverageNative( el, "click" ); - } - - // Return non-false to allow normal event-path propagation - return true; - }, - - // For cross-browser consistency, suppress native .click() on links - // Also prevent it if we're currently inside a leveraged native-event stack - _default: function( event ) { - var target = event.target; - return rcheckableType.test( target.type ) && - target.click && nodeName( target, "input" ) && - dataPriv.get( target, "click" ) || - nodeName( target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - } -}; - -// Ensure the presence of an event listener that handles manually-triggered -// synthetic events by interrupting progress until reinvoked in response to -// *native* events that it fires directly, ensuring that state changes have -// already occurred before other listeners are invoked. -function leverageNative( el, type, expectSync ) { - - // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add - if ( !expectSync ) { - if ( dataPriv.get( el, type ) === undefined ) { - jQuery.event.add( el, type, returnTrue ); - } - return; - } - - // Register the controller as a special universal handler for all event namespaces - dataPriv.set( el, type, false ); - jQuery.event.add( el, type, { - namespace: false, - handler: function( event ) { - var notAsync, result, - saved = dataPriv.get( this, type ); - - if ( ( event.isTrigger & 1 ) && this[ type ] ) { - - // Interrupt processing of the outer synthetic .trigger()ed event - // Saved data should be false in such cases, but might be a leftover capture object - // from an async native handler (gh-4350) - if ( !saved.length ) { - - // Store arguments for use when handling the inner native event - // There will always be at least one argument (an event object), so this array - // will not be confused with a leftover capture object. - saved = slice.call( arguments ); - dataPriv.set( this, type, saved ); - - // Trigger the native event and capture its result - // Support: IE <=9 - 11+ - // focus() and blur() are asynchronous - notAsync = expectSync( this, type ); - this[ type ](); - result = dataPriv.get( this, type ); - if ( saved !== result || notAsync ) { - dataPriv.set( this, type, false ); - } else { - result = {}; - } - if ( saved !== result ) { - - // Cancel the outer synthetic event - event.stopImmediatePropagation(); - event.preventDefault(); - - // Support: Chrome 86+ - // In Chrome, if an element having a focusout handler is blurred by - // clicking outside of it, it invokes the handler synchronously. If - // that handler calls `.remove()` on the element, the data is cleared, - // leaving `result` undefined. We need to guard against this. - return result && result.value; - } - - // If this is an inner synthetic event for an event with a bubbling surrogate - // (focus or blur), assume that the surrogate already propagated from triggering the - // native event and prevent that from happening again here. - // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the - // bubbling surrogate propagates *after* the non-bubbling base), but that seems - // less bad than duplication. - } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { - event.stopPropagation(); - } - - // If this is a native event triggered above, everything is now in order - // Fire an inner synthetic event with the original arguments - } else if ( saved.length ) { - - // ...and capture the result - dataPriv.set( this, type, { - value: jQuery.event.trigger( - - // Support: IE <=9 - 11+ - // Extend with the prototype to reset the above stopImmediatePropagation() - jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), - saved.slice( 1 ), - this - ) - } ); - - // Abort handling of the native event - event.stopImmediatePropagation(); - } - } - } ); -} - -jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } -}; - -jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; - - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || Date.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - code: true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, - which: true -}, jQuery.event.addProp ); - -jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { - jQuery.event.special[ type ] = { - - // Utilize native event if possible so blur/focus sequence is correct - setup: function() { - - // Claim the first handler - // dataPriv.set( this, "focus", ... ) - // dataPriv.set( this, "blur", ... ) - leverageNative( this, type, expectSync ); - - // Return false to allow normal processing in the caller - return false; - }, - trigger: function() { - - // Force setup before trigger - leverageNative( this, type ); - - // Return non-false to allow normal event-path propagation - return true; - }, - - // Suppress native focus or blur as it's already being fired - // in leverageNative. - _default: function() { - return true; - }, - - delegateType: delegateType - }; -} ); - -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); - -jQuery.fn.extend( { - - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); - - -var - - // Support: IE <=10 - 11, Edge 12 - 13 only - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - - return jQuery( elem ).children( "tbody" )[ 0 ] || elem; - } - - return elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { - elem.type = elem.type.slice( 5 ); - } else { - elem.removeAttribute( "type" ); - } - - return elem; -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.get( src ); - events = pdataOld.events; - - if ( events ) { - dataPriv.remove( dest, "handle events" ); - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = flat( args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - valueIsFunction = isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl && !node.noModule ) { - jQuery._evalUrl( node.src, { - nonce: node.nonce || node.getAttribute( "nonce" ) - }, doc ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); - } - } - } - } - } - } - - return collection; -} - -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && isAttached( node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; -} - -jQuery.extend( { - htmlPrefilter: function( html ) { - return html; - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = isAttached( elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); - -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } -} ); - -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -} ); -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; - - if ( !view || !view.opener ) { - view = window; - } - - return view.getComputedStyle( elem ); - }; - -var swap = function( elem, options, callback ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.call( elem ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - -var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); - - - -( function() { - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - // Support: Chrome <=64 - // Don't get tricked when zoom affects offsetWidth (gh-4029) - div.style.position = "absolute"; - scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableTrDimensionsVal, reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } - - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - jQuery.extend( support, { - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; - }, - - // Support: IE 9 - 11+, Edge 15 - 18+ - // IE/Edge misreport `getComputedStyle` of table rows with width/height - // set in CSS while `offset*` properties report correct values. - // Behavior in IE 9 is more subtle than in newer versions & it passes - // some versions of this test; make sure not to make it pass there! - // - // Support: Firefox 70+ - // Only Firefox includes border widths - // in computed dimensions. (gh-4529) - reliableTrDimensions: function() { - var table, tr, trChild, trStyle; - if ( reliableTrDimensionsVal == null ) { - table = document.createElement( "table" ); - tr = document.createElement( "tr" ); - trChild = document.createElement( "div" ); - - table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; - tr.style.cssText = "border:1px solid"; - - // Support: Chrome 86+ - // Height set through cssText does not get applied. - // Computed height then comes back as 0. - tr.style.height = "1px"; - trChild.style.height = "9px"; - - // Support: Android 8 Chrome 86+ - // In our bodyBackground.html iframe, - // display for all div elements is set to "inline", - // which causes a problem only in Android 8 Chrome 86. - // Ensuring the div is display: block - // gets around this issue. - trChild.style.display = "block"; - - documentElement - .appendChild( table ) - .appendChild( tr ) - .appendChild( trChild ); - - trStyle = window.getComputedStyle( tr ); - reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + - parseInt( trStyle.borderTopWidth, 10 ) + - parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; - - documentElement.removeChild( table ); - } - return reliableTrDimensionsVal; - } - } ); -} )(); - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; - - computed = computed || getStyles( elem ); - - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - - if ( ret === "" && !isAttached( elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - - -var cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style, - vendorProps = {}; - -// Return a vendor-prefixed property or undefined -function vendorPropName( name ) { - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a potentially-mapped jQuery.cssProps or vendor prefixed property -function finalPropName( name ) { - var final = jQuery.cssProps[ name ] || vendorProps[ name ]; - - if ( final ) { - return final; - } - if ( name in emptyStyle ) { - return name; - } - return vendorProps[ name ] = vendorPropName( name ) || name; -} - - -var - - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }; - -function setPositiveNumber( _elem, value, subtract ) { - - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? - - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; -} - -function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { - var i = dimension === "width" ? 1 : 0, - extra = 0, - delta = 0; - - // Adjustment may not be necessary - if ( box === ( isBorderBox ? "border" : "content" ) ) { - return 0; - } - - for ( ; i < 4; i += 2 ) { - - // Both box models exclude margin - if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); - } - - // If we get here with a content-box, we're seeking "padding" or "border" or "margin" - if ( !isBorderBox ) { - - // Add padding - delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // For "border" or "margin", add border - if ( box !== "padding" ) { - delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - - // But still keep track of it otherwise - } else { - extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - - // If we get here with a border-box (content + padding + border), we're seeking "content" or - // "padding" or "margin" - } else { - - // For "content", subtract padding - if ( box === "content" ) { - delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // For "content" or "padding", subtract border - if ( box !== "margin" ) { - delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - // Account for positive content-box scroll gutter when requested by providing computedVal - if ( !isBorderBox && computedVal >= 0 ) { - - // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border - // Assuming integer scroll gutter, subtract the rest and round down - delta += Math.max( 0, Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - computedVal - - delta - - extra - - 0.5 - - // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter - // Use an explicit zero to avoid NaN (gh-3964) - ) ) || 0; - } - - return delta; -} - -function getWidthOrHeight( elem, dimension, extra ) { - - // Start with computed style - var styles = getStyles( elem ), - - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). - // Fake content-box until we know it's needed to know the true value. - boxSizingNeeded = !support.boxSizingReliable() || extra, - isBorderBox = boxSizingNeeded && - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox, - - val = curCSS( elem, dimension, styles ), - offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); - - // Support: Firefox <=54 - // Return a confounding non-pixel value or feign ignorance, as appropriate. - if ( rnumnonpx.test( val ) ) { - if ( !extra ) { - return val; - } - val = "auto"; - } - - - // Support: IE 9 - 11 only - // Use offsetWidth/offsetHeight for when box sizing is unreliable. - // In those cases, the computed value can be trusted to be border-box. - if ( ( !support.boxSizingReliable() && isBorderBox || - - // Support: IE 10 - 11+, Edge 15 - 18+ - // IE/Edge misreport `getComputedStyle` of table rows with width/height - // set in CSS while `offset*` properties report correct values. - // Interestingly, in some cases IE 9 doesn't suffer from this issue. - !support.reliableTrDimensions() && nodeName( elem, "tr" ) || - - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - val === "auto" || - - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && - - // Make sure the element is visible & connected - elem.getClientRects().length ) { - - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // Where available, offsetWidth/offsetHeight approximate border box dimensions. - // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the - // retrieved value as a content box dimension. - valueIsBorderBox = offsetProp in elem; - if ( valueIsBorderBox ) { - val = elem[ offsetProp ]; - } - } - - // Normalize "" and auto - val = parseFloat( val ) || 0; - - // Adjust for the element's box model - return ( val + - boxModelAdjustment( - elem, - dimension, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles, - - // Provide the current computed size to request scroll gutter calculation (gh-3589) - val - ) - ) + "px"; -} - -jQuery.extend( { - - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "gridArea": true, - "gridColumn": true, - "gridColumnEnd": true, - "gridColumnStart": true, - "gridRow": true, - "gridRowEnd": true, - "gridRowStart": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: {}, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; - - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); - - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add the unit (except for certain CSS properties) - // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append - // "px" to a few hardcoded values. - if ( type === "number" && !isCustomProp ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } - - // background-* props affect original clone's values - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !( "set" in hooks ) || - ( value = hooks.set( elem, value, extra ) ) !== undefined ) { - - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } - - } else { - - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && - ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { - - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ); - - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Try prefixed name followed by the unprefixed name - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - // Convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } - - return val; - } -} ); - -jQuery.each( [ "height", "width" ], function( _i, dimension ) { - jQuery.cssHooks[ dimension ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); - } - }, - - set: function( elem, value, extra ) { - var matches, - styles = getStyles( elem ), - - // Only read styles.position if the test has a chance to fail - // to avoid forcing a reflow. - scrollboxSizeBuggy = !support.scrollboxSize() && - styles.position === "absolute", - - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) - boxSizingNeeded = scrollboxSizeBuggy || extra, - isBorderBox = boxSizingNeeded && - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra ? - boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ) : - 0; - - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && scrollboxSizeBuggy ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { - - elem.style[ dimension ] = value; - value = jQuery.css( elem, dimension ); - } - - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); - -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each( { - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // Assumes a single number if not a string - parts = typeof value === "string" ? value.split( " " ) : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( prefix !== "margin" ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -} ); - -jQuery.fn.extend( { - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( Array.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - } -} ); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || jQuery.easing._default; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { - return tween.elem[ tween.prop ]; - } - - // Passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails. - // Simple values such as "10px" are parsed to Float; - // complex values such as "rotate(1rad)" are returned as-is. - result = jQuery.css( tween.elem, tween.prop, "" ); - - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - - // Use step hook for back compat. - // Use cssHook if its there. - // Use .style if available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && ( - jQuery.cssHooks[ tween.prop ] || - tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; - -// Back compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; - -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } - - jQuery.fx.tick(); - } -} - -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = Date.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // If we include width, step value is 1 to do all cssExpand values, - // otherwise step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { - - // We're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); - - // Queue-skipping animations hijack the fx hooks - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always( function() { - - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } - - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } - } - - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; - } - - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { - - // Support: IE <=9 - 11, Edge 12 - 15 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY and Edge just mirrors - // the overflowX value there. - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { - - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } - - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { - - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; - } - } - style.display = "inline-block"; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } - - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { - - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } - - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } - - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } - - /* eslint-disable no-loop-func */ - - anim.done( function() { - - /* eslint-enable no-loop-func */ - - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } - - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // Not quite $.extend, this won't overwrite existing keys. - // Reusing 'index' because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = Animation.prefilters.length, - deferred = jQuery.Deferred().always( function() { - - // Don't match elem in the :animated selector - delete tick.elem; - } ), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - - // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ] ); - - // If there's more to do, yield - if ( percent < 1 && length ) { - return remaining; - } - - // If this was an empty animation, synthesize a final progress notification - if ( !length ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - } - - // Resolve the animation and report its conclusion - deferred.resolveWith( elem, [ animation ] ); - return false; - }, - animation = deferred.promise( { - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { - specialEasing: {}, - easing: jQuery.easing._default - }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - - // If we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // Resolve when we played the last frame; otherwise, reject - if ( gotoEnd ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - } ), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length; index++ ) { - result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - if ( isFunction( result.stop ) ) { - jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = - result.stop.bind( result ); - } - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - // Attach callbacks from options - animation - .progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - } ) - ); - - return animation; -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweeners: { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ); - adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); - return tween; - } ] - }, - - tweener: function( props, callback ) { - if ( isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.match( rnothtmlwhite ); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length; index++ ) { - prop = props[ index ]; - Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; - Animation.tweeners[ prop ].unshift( callback ); - } - }, - - prefilters: [ defaultPrefilter ], - - prefilter: function( callback, prepend ) { - if ( prepend ) { - Animation.prefilters.unshift( callback ); - } else { - Animation.prefilters.push( callback ); - } - } -} ); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing - }; - - // Go to the end state if fx are off - if ( jQuery.fx.off ) { - opt.duration = 0; - - } else { - if ( typeof opt.duration !== "number" ) { - if ( opt.duration in jQuery.fx.speeds ) { - opt.duration = jQuery.fx.speeds[ opt.duration ]; - - } else { - opt.duration = jQuery.fx.speeds._default; - } - } - } - - // Normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend( { - fadeTo: function( speed, to, easing, callback ) { - - // Show any hidden elements after setting opacity to 0 - return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() - - // Animate to the value specified - .end().animate( { opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || dataPriv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue ) { - this.queue( type || "fx", [] ); - } - - return this.each( function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = dataPriv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && - ( type == null || timers[ index ].queue === type ) ) { - - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // Start the next in the queue if the last step wasn't forced. - // Timers currently will call their complete callbacks, which - // will dequeue but only if they were gotoEnd. - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - } ); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each( function() { - var index, - data = dataPriv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // Enable finishing flag on private data - data.finish = true; - - // Empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // Look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // Look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // Turn off finishing flag - delete data.finish; - } ); - } -} ); - -jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -} ); - -// Generate shortcuts for custom animations -jQuery.each( { - slideDown: genFx( "show" ), - slideUp: genFx( "hide" ), - slideToggle: genFx( "toggle" ), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -} ); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = Date.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - - // Run the timer and safely remove it when done (allowing for external removal) - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - jQuery.fx.start(); -}; - -jQuery.fx.interval = 13; -jQuery.fx.start = function() { - if ( inProgress ) { - return; - } - - inProgress = true; - schedule(); -}; - -jQuery.fx.stop = function() { - inProgress = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = window.setTimeout( next, time ); - hooks.stop = function() { - window.clearTimeout( timeout ); - }; - } ); -}; - - -( function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only - // Must access selectedIndex to make default options select - support.optSelected = opt.selected; - - // Support: IE <=11 only - // An input loses its value after becoming a radio - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -} )(); - - -var boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend( { - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each( function() { - jQuery.removeAttr( this, name ); - } ); - } -} ); - -jQuery.extend( { - attr: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set attributes on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - // Attribute hooks are determined by the lowercase version - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - hooks = jQuery.attrHooks[ name.toLowerCase() ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); - } - - if ( value !== undefined ) { - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - } - - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - elem.setAttribute( name, value + "" ); - return value; - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? undefined : ret; - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - nodeName( elem, "input" ) ) { - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - removeAttr: function( elem, value ) { - var name, - i = 0, - - // Attribute names can contain non-HTML whitespace characters - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 - attrNames = value && value.match( rnothtmlwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( ( name = attrNames[ i++ ] ) ) { - elem.removeAttribute( name ); - } - } - } -} ); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; - -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle, - lowercaseName = name.toLowerCase(); - - if ( !isXML ) { - - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ lowercaseName ]; - attrHandle[ lowercaseName ] = ret; - ret = getter( elem, name, isXML ) != null ? - lowercaseName : - null; - attrHandle[ lowercaseName ] = handle; - } - return ret; - }; -} ); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i, - rclickable = /^(?:a|area)$/i; - -jQuery.fn.extend( { - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each( function() { - delete this[ jQuery.propFix[ name ] || name ]; - } ); - } -} ); - -jQuery.extend( { - prop: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set properties on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - return ( elem[ name ] = value ); - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - return elem[ name ]; - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - - // Support: IE <=9 - 11 only - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - if ( tabindex ) { - return parseInt( tabindex, 10 ); - } - - if ( - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && - elem.href - ) { - return 0; - } - - return -1; - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - } -} ); - -// Support: IE <=11 only -// Accessing the selectedIndex property -// forces the browser to respect setting selected -// on the option -// The getter ensures a default option is selected -// when in an optgroup -// eslint rule "no-unused-expressions" is disabled for this code -// since it considers such accessions noop -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - }, - set: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - }; -} - -jQuery.each( [ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -} ); - - - - - // Strip and collapse whitespace according to HTML spec - // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace - function stripAndCollapse( value ) { - var tokens = value.match( rnothtmlwhite ) || []; - return tokens.join( " " ); - } - - -function getClass( elem ) { - return elem.getAttribute && elem.getAttribute( "class" ) || ""; -} - -function classesToArray( value ) { - if ( Array.isArray( value ) ) { - return value; - } - if ( typeof value === "string" ) { - return value.match( rnothtmlwhite ) || []; - } - return []; -} - -jQuery.fn.extend( { - addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - if ( !arguments.length ) { - return this.attr( "class", "" ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isValidValue = type === "string" || Array.isArray( value ); - - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( isFunction( value ) ) { - return this.each( function( i ) { - jQuery( this ).toggleClass( - value.call( this, i, getClass( this ), stateVal ), - stateVal - ); - } ); - } - - return this.each( function() { - var className, i, self, classNames; - - if ( isValidValue ) { - - // Toggle individual class names - i = 0; - self = jQuery( this ); - classNames = classesToArray( value ); - - while ( ( className = classNames[ i++ ] ) ) { - - // Check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( value === undefined || type === "boolean" ) { - className = getClass( this ); - if ( className ) { - - // Store className if set - dataPriv.set( this, "__className__", className ); - } - - // If the element has a class name or if we're passed `false`, - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" - ); - } - } - } ); - }, - - hasClass: function( selector ) { - var className, elem, - i = 0; - - className = " " + selector + " "; - while ( ( elem = this[ i++ ] ) ) { - if ( elem.nodeType === 1 && - ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; - } - } - - return false; - } -} ); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend( { - val: function( value ) { - var hooks, ret, valueIsFunction, - elem = this[ 0 ]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || - jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && - "get" in hooks && - ( ret = hooks.get( elem, "value" ) ) !== undefined - ) { - return ret; - } - - ret = elem.value; - - // Handle most common string cases - if ( typeof ret === "string" ) { - return ret.replace( rreturn, "" ); - } - - // Handle cases where value is null/undef or number - return ret == null ? "" : ret; - } - - return; - } - - valueIsFunction = isFunction( value ); - - return this.each( function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( valueIsFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( Array.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - } ); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - } ); - } -} ); - -jQuery.extend( { - valHooks: { - option: { - get: function( elem ) { - - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - - // Support: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) - // Strip and collapse whitespace - // https://html.spec.whatwg.org/#strip-and-collapse-whitespace - stripAndCollapse( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, i, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one", - values = one ? null : [], - max = one ? index + 1 : options.length; - - if ( index < 0 ) { - i = max; - - } else { - i = one ? index : 0; - } - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - - // Don't return options that are disabled or in a disabled optgroup - !option.disabled && - ( !option.parentNode.disabled || - !nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - - /* eslint-disable no-cond-assign */ - - if ( option.selected = - jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 - ) { - optionSet = true; - } - - /* eslint-enable no-cond-assign */ - } - - // Force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -} ); - -// Radios and checkboxes getter/setter -jQuery.each( [ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( Array.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } -} ); - - - - -// Return jQuery for attributes-only inclusion - - -support.focusin = "onfocusin" in window; - - -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - stopPropagationCallback = function( e ) { - e.stopPropagation(); - }; - -jQuery.extend( jQuery.event, { - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = lastElement = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "." ) > -1 ) { - - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split( "." ); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf( ":" ) < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join( "." ); - event.rnamespace = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === ( elem.ownerDocument || document ) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - lastElement = cur; - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && - dataPriv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( ( !special._default || - special._default.apply( eventPath.pop(), data ) === false ) && - acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - - if ( event.isPropagationStopped() ) { - lastElement.addEventListener( type, stopPropagationCallback ); - } - - elem[ type ](); - - if ( event.isPropagationStopped() ) { - lastElement.removeEventListener( type, stopPropagationCallback ); - } - - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - // Piggyback on a donor event to simulate a different one - // Used only for `focus(in | out)` events - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - } - ); - - jQuery.event.trigger( e, null, elem ); - } - -} ); - -jQuery.fn.extend( { - - trigger: function( type, data ) { - return this.each( function() { - jQuery.event.trigger( type, data, this ); - } ); - }, - triggerHandler: function( type, data ) { - var elem = this[ 0 ]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -} ); - - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - - // Handle: regular nodes (via `this.ownerDocument`), window - // (via `this.document`) & document (via `this`). - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = { guid: Date.now() }; - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml, parserErrorElem; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) {} - - parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; - if ( !xml || parserErrorElem ) { - jQuery.error( "Invalid XML: " + ( - parserErrorElem ? - jQuery.map( parserErrorElem.childNodes, function( el ) { - return el.textContent; - } ).join( "\n" ) : - data - ) ); - } - return xml; -}; - - -var - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( Array.isArray( obj ) ) { - - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - - // Item is non-scalar (array or object), encode its numeric index. - buildParams( - prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", - v, - traditional, - add - ); - } - } ); - - } else if ( !traditional && toType( obj ) === "object" ) { - - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, valueOrFunction ) { - - // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? - valueOrFunction() : - valueOrFunction; - - s[ s.length ] = encodeURIComponent( key ) + "=" + - encodeURIComponent( value == null ? "" : value ); - }; - - if ( a == null ) { - return ""; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - } ); - - } else { - - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ); -}; - -jQuery.fn.extend( { - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map( function() { - - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - } ).filter( function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - } ).map( function( _i, elem ) { - var val = jQuery( this ).val(); - - if ( val == null ) { - return null; - } - - if ( Array.isArray( val ) ) { - return jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ); - } - - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ).get(); - } -} ); - - -var - r20 = /%20/g, - rhash = /#.*$/, - rantiCache = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat( "*" ), - - // Anchor tag for parsing the document origin - originAnchor = document.createElement( "a" ); - -originAnchor.href = location.href; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; - - if ( isFunction( func ) ) { - - // For each dataType in the dataTypeExpression - while ( ( dataType = dataTypes[ i++ ] ) ) { - - // Prepend if requested - if ( dataType[ 0 ] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); - - // Otherwise append - } else { - ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && - !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - } ); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s.throws ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { - state: "parsererror", - error: conv ? e : "No conversion from " + prev + " to " + current - }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend( { - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: location.href, - type: "GET", - isLocal: rlocalProtocol.test( location.protocol ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /\bxml\b/, - html: /\bhtml/, - json: /\bjson\b/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": JSON.parse, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - - // URL without anti-cache param - cacheURL, - - // Response headers - responseHeadersString, - responseHeaders, - - // timeout handle - timeoutTimer, - - // Url cleanup var - urlAnchor, - - // Request state (becomes false upon send and true upon completion) - completed, - - // To know if global events are to be dispatched - fireGlobals, - - // Loop variable - i, - - // uncached part of the url - uncached, - - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - - // Callbacks context - callbackContext = s.context || s, - - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && - ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - - // Status-dependent callbacks - statusCode = s.statusCode || {}, - - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - - // Default abort message - strAbort = "canceled", - - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( completed ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() + " " ] = - ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) - .concat( match[ 2 ] ); - } - } - match = responseHeaders[ key.toLowerCase() + " " ]; - } - return match == null ? null : match.join( ", " ); - }, - - // Raw string - getAllResponseHeaders: function() { - return completed ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( completed == null ) { - name = requestHeadersNames[ name.toLowerCase() ] = - requestHeadersNames[ name.toLowerCase() ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( completed == null ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( completed ) { - - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } else { - - // Lazy-add the new callbacks in a way that preserves old ones - for ( code in map ) { - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ); - - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || location.href ) + "" ) - .replace( rprotocol, location.protocol + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; - - // A cross-domain request is in order when the origin doesn't match the current origin. - if ( s.crossDomain == null ) { - urlAnchor = document.createElement( "a" ); - - // Support: IE <=8 - 11, Edge 12 - 15 - // IE throws exception on accessing the href property if url is malformed, - // e.g. http://example.com:80x/ - try { - urlAnchor.href = s.url; - - // Support: IE <=8 - 11 only - // Anchor's host property isn't correctly set when s.url is relative - urlAnchor.href = urlAnchor.href; - s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== - urlAnchor.protocol + "//" + urlAnchor.host; - } catch ( e ) { - - // If there is an error parsing the URL, assume it is crossDomain, - // it can be rejected by the transport if it is invalid - s.crossDomain = true; - } - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( completed ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) - fireGlobals = jQuery.event && s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - // Remove hash to simplify url manipulation - cacheURL = s.url.replace( rhash, "" ); - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // Remember the hash so we can put it back - uncached = s.url.slice( cacheURL.length ); - - // If data is available and should be processed, append data to url - if ( s.data && ( s.processData || typeof s.data === "string" ) ) { - cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add or update anti-cache param if needed - if ( s.cache === false ) { - cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + - uncached; - } - - // Put hash and anti-cache on the URL that will be requested (gh-1732) - s.url = cacheURL + uncached; - - // Change '%20' to '+' if this is encoded form body content (gh-2658) - } else if ( s.data && s.processData && - ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { - s.data = s.data.replace( r20, "+" ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? - s.accepts[ s.dataTypes[ 0 ] ] + - ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && - ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { - - // Abort if not done already and return - return jqXHR.abort(); - } - - // Aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - completeDeferred.add( s.complete ); - jqXHR.done( s.success ); - jqXHR.fail( s.error ); - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - - // If request was aborted inside ajaxSend, stop there - if ( completed ) { - return jqXHR; - } - - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = window.setTimeout( function() { - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - completed = false; - transport.send( requestHeaders, done ); - } catch ( e ) { - - // Rethrow post-completion exceptions - if ( completed ) { - throw e; - } - - // Propagate others as results - done( -1, e ); - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Ignore repeat invocations - if ( completed ) { - return; - } - - completed = true; - - // Clear timeout if it exists - if ( timeoutTimer ) { - window.clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Use a noop converter for missing script but not if jsonp - if ( !isSuccess && - jQuery.inArray( "script", s.dataTypes ) > -1 && - jQuery.inArray( "json", s.dataTypes ) < 0 ) { - s.converters[ "text script" ] = function() {}; - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader( "Last-Modified" ); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader( "etag" ); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - - // Extract error from statusText and normalize for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -} ); - -jQuery.each( [ "get", "post" ], function( _i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - - // Shift arguments if data argument was omitted - if ( isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - // The url can be an options object (which then must have .url) - return jQuery.ajax( jQuery.extend( { - url: url, - type: method, - dataType: type, - data: data, - success: callback - }, jQuery.isPlainObject( url ) && url ) ); - }; -} ); - -jQuery.ajaxPrefilter( function( s ) { - var i; - for ( i in s.headers ) { - if ( i.toLowerCase() === "content-type" ) { - s.contentType = s.headers[ i ] || ""; - } - } -} ); - - -jQuery._evalUrl = function( url, options, doc ) { - return jQuery.ajax( { - url: url, - - // Make this explicit, since user can override this through ajaxSetup (#11264) - type: "GET", - dataType: "script", - cache: true, - async: false, - global: false, - - // Only evaluate the response if it is successful (gh-4126) - // dataFilter is not invoked for failure responses, so using it instead - // of the default converter is kludgy but it works. - converters: { - "text script": function() {} - }, - dataFilter: function( response ) { - jQuery.globalEval( response, options, doc ); - } - } ); -}; - - -jQuery.fn.extend( { - wrapAll: function( html ) { - var wrap; - - if ( this[ 0 ] ) { - if ( isFunction( html ) ) { - html = html.call( this[ 0 ] ); - } - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map( function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - } ).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( isFunction( html ) ) { - return this.each( function( i ) { - jQuery( this ).wrapInner( html.call( this, i ) ); - } ); - } - - return this.each( function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - } ); - }, - - wrap: function( html ) { - var htmlIsFunction = isFunction( html ); - - return this.each( function( i ) { - jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); - } ); - }, - - unwrap: function( selector ) { - this.parent( selector ).not( "body" ).each( function() { - jQuery( this ).replaceWith( this.childNodes ); - } ); - return this; - } -} ); - - -jQuery.expr.pseudos.hidden = function( elem ) { - return !jQuery.expr.pseudos.visible( elem ); -}; -jQuery.expr.pseudos.visible = function( elem ) { - return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); -}; - - - - -jQuery.ajaxSettings.xhr = function() { - try { - return new window.XMLHttpRequest(); - } catch ( e ) {} -}; - -var xhrSuccessStatus = { - - // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - xhr.open( - options.type, - options.url, - options.async, - options.username, - options.password - ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); - - try { - - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -} ); - - - - -// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) -jQuery.ajaxPrefilter( function( s ) { - if ( s.crossDomain ) { - s.contents.script = false; - } -} ); - -// Install script dataType -jQuery.ajaxSetup( { - accepts: { - script: "text/javascript, application/javascript, " + - "application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /\b(?:java|ecma)script\b/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -} ); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -} ); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - - // This transport only deals with cross domain or forced-by-attrs requests - if ( s.crossDomain || s.scriptAttrs ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery( " - - - - - - HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION

-

HDUVA builds on a generative approach within the framework of variational autoencoders to facilitate generalization to new domains without supervision. HDUVA learns representations that disentangle domain-specific information from class-label specific information even in complex settings where domain structure is not observed during training.

-
-

Model Overview

-

More specifically, HDUVA is based on three latent variables that are used to model distinct sources of variation and are denoted as \(z_y\), \(z_d\) and \(z_x\). \(z_y\) represents class specific information, \(z_d\) represents domain specific information and \(z_x\) models residual variance of the input. We introduce an additional hierarchical level and use a continuous latent representation s to model (potentially unobserved) domain structure. This means that we can encourage disentanglement of the latent variables through conditional priors without the need of conditioning on a one-hot-encoded, observed domain label. The model along with its parameters and hyperparameters is shown in Figure 1:

-
-PGM for HDUVA -
Figure 1: Probabilistic graphical model for HDUVA:Hierarchical Domain Unsupervised Variational Autoencoding.
-
-

Note that as part of the model a latent representation of \(X\) is concatentated with \(s\) and \(z_d\) (dashed arrows), requiring respecive encoder networks.

-
-
-

Evidence lower bound and overall loss

-

The ELBO of the model can be decomposed into 4 different terms:

-

Likelihood: \(E_{q(z_d, s|x), q(z_x|x), q(z_y|x)}\log p_{\theta}(x|s, z_d, z_x, z_y)\)

-

KL divergence weighted as in the Beta-VAE: \(-\beta_x KL(q_{\phi_x}(z_x|x)||p_{\theta_x}(z_x)) - \beta_y KL(q_{\phi_y}(z_y|x)||p_{\theta_y}(z_y|y))\)

-

Hierarchical KL loss (domain term): \(- \beta_d E_{q_{\phi_s}(s|x), q_{\phi_d}(z_d|x, s)} \log \frac{q_{\phi_d}(z_d|x, s)}{p_{\theta_d}(z_d|s)}\)

-

Hierarchical KL loss (topic term): \(-\beta_t E_{q_{\phi_s}(s|x)}KL(q_{\phi_s}(s|x)||p_{\theta_s}(s|\alpha))\)

-

In addition, we construct the overall loss by adding an auxiliary classsifier, by adding an additional term to the ELBO loss, weighted with \(\gamma_y\):

-
-
-

Hyperparameters loss function

-

For fitting the model, we need to specify the 4 \(\beta\)-weights related to the the different terms of the ELBO ( \(\beta_x\) , \(\beta_y\), \(\beta_d\), \(\beta_t\)) as well as \(\gamma_y\).

-
-
-

Model parameters

-

In addition to these hyperparameters, the following model parameters can be specified:

-
    -
  • Size of latent space for domain-specific information: zd_dim

  • -
  • Size of latent space for residual variance: zx_dim

  • -
  • Size of latent space for class-specific information: zy_dim

  • -
  • Size of latent space for topics \(s\): topic_dim

  • -
  • Size of latent space for latent image representation for topic: topic_h_dim

  • -
  • Size of latent space for latent image representation for domain: img_h_dim

  • -
-

Finally, 2 models need to be specified: A network converting an image to a topic distribution (of size topic_h_dim) and an encoder converting an image to a latent representation that can be concatenated to \(z_d\) (size img_h_dim). The names and paths of the networks are:

-
    -
  • nname_topic_distrib_img2topic

  • -
  • npath_topic_distrib_img2topic

  • -
-

and

-
    -
  • nname_encoder_sandwich_layer_img2h4zd

  • -
  • npath_encoder_sandwich_layer_img2h4zd

  • -
-
-
-

Hyperparameter warmup

-

Finally, the number of epochs for hyper-parameter warm-up can be specified via the argument warmup

-

Please cite our paper if you find it useful!

-
@inproceedings{sun2021hierarchical,
-  title={Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization},
-  author={Sun, Xudong and Buettner, Florian},
-  booktitle={ICLR 2021 RobustML workshop, https://arxiv.org/pdf/2101.09436.pdf},
-  year={2021}
-}
-
-
-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/docHDUVA.md b/docs/build/html/docHDUVA.md deleted file mode 100644 index edb680595..000000000 --- a/docs/build/html/docHDUVA.md +++ /dev/null @@ -1,65 +0,0 @@ -# HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION - -HDUVA builds on a generative approach within the framework of variational autoencoders to facilitate generalization to new domains without supervision. HDUVA learns representations that disentangle domain-specific information from class-label specific information even in complex settings where domain structure is not observed during training. - -## Model Overview -More specifically, HDUVA is based on three latent variables that are used to model distinct sources of variation and are denoted as $z_y$, $z_d$ and $z_x$. $z_y$ represents class specific information, $z_d$ represents domain specific information and $z_x$ models residual variance of the input. We introduce an additional hierarchical level and use a continuous latent representation s to model (potentially unobserved) domain structure. This means that we can encourage disentanglement of the latent variables through conditional priors without the need of conditioning on a one-hot-encoded, observed domain label. The model along with its parameters and hyperparameters is shown in Figure 1: - -
- PGM for HDUVA -
Figure 1: Probabilistic graphical model for HDUVA:Hierarchical Domain Unsupervised Variational Autoencoding.
-
- - - -Note that as part of the model a latent representation of $X$ is concatentated with $s$ and $z_d$ (dashed arrows), requiring respecive encoder networks. - -## Evidence lower bound and overall loss -The ELBO of the model can be decomposed into 4 different terms: - -Likelihood: $E_{q(z_d, s|x), q(z_x|x), q(z_y|x)}\log p_{\theta}(x|s, z_d, z_x, z_y)$ - -KL divergence weighted as in the Beta-VAE: $-\beta_x KL(q_{\phi_x}(z_x|x)||p_{\theta_x}(z_x)) - \beta_y KL(q_{\phi_y}(z_y|x)||p_{\theta_y}(z_y|y))$ - -Hierarchical KL loss (domain term): $- \beta_d E_{q_{\phi_s}(s|x), q_{\phi_d}(z_d|x, s)} \log \frac{q_{\phi_d}(z_d|x, s)}{p_{\theta_d}(z_d|s)}$ - -Hierarchical KL loss (topic term): $-\beta_t E_{q_{\phi_s}(s|x)}KL(q_{\phi_s}(s|x)||p_{\theta_s}(s|\alpha))$ - -In addition, we construct the overall loss by adding an auxiliary classsifier, by adding an additional term to the ELBO loss, weighted with $\gamma_y$: - - -## Hyperparameters loss function -For fitting the model, we need to specify the 4 $\beta$-weights related to the the different terms of the ELBO ( $\beta_x$ , $\beta_y$, $\beta_d$, $\beta_t$) as well as $\gamma_y$. - -## Model parameters -In addition to these hyperparameters, the following model parameters can be specified: - -- Size of latent space for domain-specific information: zd_dim -- Size of latent space for residual variance: zx_dim -- Size of latent space for class-specific information: zy_dim -- Size of latent space for topics $s$: topic_dim -- Size of latent space for latent image representation for topic: topic_h_dim -- Size of latent space for latent image representation for domain: img_h_dim - -Finally, 2 models need to be specified: A network converting an image to a topic distribution (of size topic_h_dim) and an encoder converting an image to a latent representation that can be concatenated to $z_d$ (size img_h_dim). The names and paths of the networks are: - -- nname_topic_distrib_img2topic -- npath_topic_distrib_img2topic - -and -- nname_encoder_sandwich_layer_img2h4zd -- npath_encoder_sandwich_layer_img2h4zd - - -## Hyperparameter warmup -Finally, the number of epochs for hyper-parameter warm-up can be specified via the argument warmup - -Please cite our paper if you find it useful! -```text -@inproceedings{sun2021hierarchical, - title={Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization}, - author={Sun, Xudong and Buettner, Florian}, - booktitle={ICLR 2021 RobustML workshop, https://arxiv.org/pdf/2101.09436.pdf}, - year={2021} -} -``` diff --git a/docs/build/html/docJiGen.html b/docs/build/html/docJiGen.html deleted file mode 100644 index 770c2cda5..000000000 --- a/docs/build/html/docJiGen.html +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JiGen — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -
-

JiGen

-

The JiGen method proposed in https://arxiv.org/abs/2007.01434 by Carlucci et al. extends the understanding of the concept of spatial correlation in the neuronal network by training the network not only on a classification task, but also on solving jigsaw puzzles.

-

For the jigsaw puzzles the images are split into \(n \times n\) patches and permutated.

-

The model is to predict the permutation index which result in the permutated image.

-

To be able to solve the classification problem and the jigsaw puzzle in parallel, shuffled and ordered images will first be fed into a convolutional network for feature extraction and will then be given to the image classifier and the jigsaw classifier.

-

For the training of classificaiton task the network uses a cross-entropy loss for both tasks while weighting the jigsaw classifier by a hyper parameter. Additionally the relative ratio or probability of shuffling the tiles of one instance from training data set is given by another hyper parameter.

-

The advantage of this method is that is does not require domain label, as the jigsaw puzzle can be solved despite the missing domain labels.

-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/docJiGen.md b/docs/build/html/docJiGen.md deleted file mode 100644 index a26331b04..000000000 --- a/docs/build/html/docJiGen.md +++ /dev/null @@ -1,14 +0,0 @@ -# JiGen - -The JiGen method proposed in [https://arxiv.org/abs/2007.01434](https://arxiv.org/abs/1903.06864) by Carlucci et al. extends the understanding of the concept of spatial correlation in the neuronal network by training the network not only on a classification task, but also on solving jigsaw puzzles. - -For the jigsaw puzzles the images are split into $n \times n$ patches and permutated. - -The model is to predict the permutation index which result in the permutated image. - -To be able to solve the classification problem and the jigsaw puzzle in parallel, shuffled and ordered images will first be fed into a convolutional network for feature extraction and will then be given to the image classifier and the jigsaw classifier. - -For the training of classificaiton task the network uses a cross-entropy loss for both tasks while weighting the jigsaw classifier by a hyper parameter. Additionally the relative ratio or probability of shuffling the tiles of one instance from training data set is given by another hyper parameter. - -The advantage of this method is that is does not require domain label, as the jigsaw puzzle can be solved despite the missing domain labels. - diff --git a/docs/build/html/doc_algos.html b/docs/build/html/doc_algos.html deleted file mode 100644 index 182a49a9a..000000000 --- a/docs/build/html/doc_algos.html +++ /dev/null @@ -1,465 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Overview of implemented models and algorithms — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

Overview of implemented models and algorithms

-

Note DomainLab decomposes the concept of model from network and algorithm. That is, the model only defines the loss of the neural network, while the architecture of the neural network can be specified independently as a component of the model, and algorithm is model with a specified trainer and observer. Algorithm share the same name as model with a default trainer specified.

-
-

algorithm “deepall”

-

Pool all domains together and train an ERM (empirical risk minimization) model

-
-
-

algorithm “matchdg”

-

Mahajan, Divyat, Shruti Tople, and Amit Sharma. “Domain generalization using causal matching.” International Conference on Machine Learning. PMLR, 2021.

-
-
-

algorithm “diva”

-

Ilse, Maximilian, et al. “Diva: Domain invariant variational autoencoders.” Medical Imaging with Deep Learning. PMLR, 2020.

-
-
-

algorithm “hduva”

-

Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization: https://arxiv.org/pdf/2101.09436.pdf, ICLR 2020 RobustML.

-
-
-

algorithm “dann”:

-

Ganin, Yaroslav, et al. “Domain-adversarial training of neural networks.” The journal of machine learning research 17.1 (2016): 2096-2030.

-
-
-

algorithm “jigen”:

-

Carlucci, Fabio M., et al. “Domain generalization by solving jigsaw puzzles.” Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019. https://arxiv.org/abs/1903.06864

-
-
-

algorithm deepall, dann, diva with trainer “dial”

-

Levi, Matan, Idan Attias, and Aryeh Kontorovich. “Domain invariant adversarial learning.”, Transactions on Machine Learning Research, arXiv preprint arXiv:2104.00322 (2021).

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/doc_algos.md b/docs/build/html/doc_algos.md deleted file mode 100644 index 664f40bfc..000000000 --- a/docs/build/html/doc_algos.md +++ /dev/null @@ -1,23 +0,0 @@ -# Overview of implemented models and algorithms - -Note DomainLab decomposes the concept of model from network and algorithm. That is, the model only defines the loss of the neural network, while the architecture of the neural network can be specified independently as a component of the model, and algorithm is model with a specified trainer and observer. Algorithm share the same name as model with a default trainer specified. - -## algorithm "deepall" -Pool all domains together and train an ERM (empirical risk minimization) model - -## algorithm "matchdg" -Mahajan, Divyat, Shruti Tople, and Amit Sharma. "Domain generalization using causal matching." International Conference on Machine Learning. PMLR, 2021. -## algorithm "diva" -Ilse, Maximilian, et al. "Diva: Domain invariant variational autoencoders." Medical Imaging with Deep Learning. PMLR, 2020. - -## algorithm "hduva" -Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization: https://arxiv.org/pdf/2101.09436.pdf, ICLR 2020 RobustML. - -## algorithm "dann": -Ganin, Yaroslav, et al. "Domain-adversarial training of neural networks." The journal of machine learning research 17.1 (2016): 2096-2030. - -## algorithm "jigen": -Carlucci, Fabio M., et al. "Domain generalization by solving jigsaw puzzles." Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019. https://arxiv.org/abs/1903.06864 - -## algorithm deepall, dann, diva with trainer "dial" -Levi, Matan, Idan Attias, and Aryeh Kontorovich. "Domain invariant adversarial learning.", Transactions on Machine Learning Research, arXiv preprint arXiv:2104.00322 (2021). diff --git a/docs/build/html/doc_benchmark.html b/docs/build/html/doc_benchmark.html deleted file mode 100644 index bb6fcae71..000000000 --- a/docs/build/html/doc_benchmark.html +++ /dev/null @@ -1,386 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Benchmarking with DomainLab — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

Benchmarking with DomainLab

-

The package offers the ability to benchmark different algorithms against each other. -The results are collected in a csv file, but also prepared in charts.

-

Within each benchmark, two aspects are considered:

-
    -
  1. Stochastic variation: Variation of the performance with respect to different random seeds.

  2. -
  3. Sensitivity to selected hyperparameters: By sampling hyperparameters randomly, -the performance with respect to different hyperparameter choices is investigated.

  4. -
-
-

Setting up a benchmark

-

The benchmark is configured in a yaml file. We refer to the -demo_benchmark.yaml -for a documented example. As one can see here, the user has to select:

-
    -
  • Common arguments for all tasks. This typically includes the dataset on which the benchmark -shall be performed, as well as the number of epochs and batch size for training. -Here also the number of different random seeds and hyperparameter samples is set.

  • -
  • The domains which are used as leave-one-out for testing.

  • -
  • Different tasks, where each task contains: (1) Fixed parameters specific for this task, -typically the algorithm name and related arguments and (2) varying hyperparameters, for which -the sensitivity shall be investigated.

  • -
-

Set sampling_seed for a fully reproducible benchmark.

-
-
-

Configure hyperparameter sampling

-

An example files of the possibilities for hyperparameter sampling is -demo_hypeparameter_sampling.yml. -This file is of course an extract of demo_benchmark.yaml, -the sampling for benchmarks is specified directly in this single configuration file.

-

In this example we can see:

-
    -
  • Every node containing aname is considered as a task

  • -
  • Hyperparameters can be sampled from different distributions and

  • -
  • Constraints between the hyperparameters of the same task can be specified.

  • -
  • By using the categorical distribution type, a list of valid values for a hyperparameter can be specified.

  • -
  • Equality constraints are not supported in the constraints section. To -enforce equality of two hyperparameters use the reference key, see p4 of Task1. -References are supported only to sampled hyperparameters, referencing a reference -results in undefined behaviour.

  • -
-

Note that for sampling, there is always first a sample drawn ignoring the constraints, which -is then possibly rejected by the constraints. If 10,000 samples are rejected in a row, the sampling -aborts with error.

-
-
-

Running a benchmark

-

For executing the benchmark, a sample command can be found -here. -If several cores are provided, the benchmark is parallelized per hyperparameter sample and -task.

-
-
-

Obtained results

-

All files created by this benchmark are saved in the given output directory. -The sampled hyperparameters can be found in hyperparameters.csv. -The performance of the different runs can be found in results.csv. Moreover, there is -the graphics subdirectory, in which the values from results.csv are visualized for interpretation.

-
-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/doc_benchmark.md b/docs/build/html/doc_benchmark.md deleted file mode 100644 index 7006ca05f..000000000 --- a/docs/build/html/doc_benchmark.md +++ /dev/null @@ -1,55 +0,0 @@ -# Benchmarking with DomainLab - -The package offers the ability to benchmark different algorithms against each other. -The results are collected in a csv file, but also prepared in charts. - -Within each benchmark, two aspects are considered: -1. Stochastic variation: Variation of the performance with respect to different random seeds. -2. Sensitivity to selected hyperparameters: By sampling hyperparameters randomly, -the performance with respect to different hyperparameter choices is investigated. - -## Setting up a benchmark -The benchmark is configured in a yaml file. We refer to the -[demo_benchmark.yaml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_benchmark.yaml) -for a documented example. As one can see here, the user has to select: -- Common arguments for all tasks. This typically includes the dataset on which the benchmark -shall be performed, as well as the number of epochs and batch size for training. -Here also the number of different random seeds and hyperparameter samples is set. -- The domains which are used as leave-one-out for testing. -- Different tasks, where each task contains: (1) Fixed parameters specific for this task, -typically the algorithm name and related arguments and (2) varying hyperparameters, for which -the sensitivity shall be investigated. - -Set `sampling_seed` for a fully reproducible benchmark. - -## Configure hyperparameter sampling -An example files of the possibilities for hyperparameter sampling is -[demo_hypeparameter_sampling.yml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_hyperparameter_sampling.yml). -This file is of course an extract of [demo_benchmark.yaml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_benchmark.yaml), -the sampling for benchmarks is specified directly in this single configuration file. - -In this example we can see: -- Every node containing `aname` is considered as a task -- Hyperparameters can be sampled from different distributions and -- Constraints between the hyperparameters of the same task can be specified. -- By using the `categorical` distribution type, a list of valid values for a hyperparameter can be specified. -- Equality constraints are not supported in the constraints section. To -enforce equality of two hyperparameters use the `reference` key, see `p4` of `Task1`. -References are supported only to sampled hyperparameters, referencing a reference -results in undefined behaviour. - -Note that for sampling, there is always first a sample drawn ignoring the constraints, which -is then possibly rejected by the constraints. If 10,000 samples are rejected in a row, the sampling -aborts with error. - -## Running a benchmark -For executing the benchmark, a sample command can be found -[here](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/benchmark/run_snakemake.sh). -If several cores are provided, the benchmark is parallelized per hyperparameter sample and -task. - -## Obtained results -All files created by this benchmark are saved in the given output directory. -The sampled hyperparameters can be found in `hyperparameters.csv`. -The performance of the different runs can be found in `results.csv`. Moreover, there is -the `graphics` subdirectory, in which the values from `results.csv` are visualized for interpretation. diff --git a/docs/build/html/doc_custom_nn.html b/docs/build/html/doc_custom_nn.html deleted file mode 100644 index 621698ac5..000000000 --- a/docs/build/html/doc_custom_nn.html +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Custom Neural Network — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

Custom Neural Network

-

To use a custom neural network, the user has to implement the following signature in a python file and feed into this library via --npath.

-
def build_feat_extract_net(dim_y, remove_last_layer):
-
-
-

See examples below from --npath=examples/nets/resnet.py where the examples can be found in the examples folder of the code repository.

-
-

Custom Neural Network Examples

-

https://github.com/marrlab/DomainLab/blob/master/examples/nets/resnet.py

-
-

algorithm ‘deepall’ with custom neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py
-
-
-
-
-

algorithm ‘matchdg’ with custom neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py
-
-
-
-
-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/doc_custom_nn.md b/docs/build/html/doc_custom_nn.md deleted file mode 100644 index 7126884ba..000000000 --- a/docs/build/html/doc_custom_nn.md +++ /dev/null @@ -1,26 +0,0 @@ -# Custom Neural Network - -To use a custom neural network, the user has to implement the following signature in a python file and feed into this library via `--npath`. - - -``` -def build_feat_extract_net(dim_y, remove_last_layer): -``` - -See examples below from `--npath=examples/nets/resnet.py` where the examples can be found in the examples folder of the code repository. - -## Custom Neural Network Examples - - - -### algorithm 'deepall' with custom neural network - -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py -``` - -### algorithm 'matchdg' with custom neural network - -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py -``` diff --git a/docs/build/html/doc_diva.html b/docs/build/html/doc_diva.html deleted file mode 100644 index 654b01915..000000000 --- a/docs/build/html/doc_diva.html +++ /dev/null @@ -1,371 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DIVA: Domain Invariant Variational Autoencoders — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- -
-
-
- -
-
-
-
-
-
- - -
-
-
- -
-
- -
-

DIVA: Domain Invariant Variational Autoencoders

-

DIVA approaches the domain generalization problem with a variational autoencoder -with three latent variables, using three independent encoders.

-

By encouraging the network to store the domain, -class and residual features in one of the latent space respectively the class specific information -shall be disentangled.

-

In order to obtain marginally independent latent variables, the density of the domain -and class latent space is conditioned on the domain and class respectively. These densities are parameterized -by learnable parameters. During training, all three latent variables are then fed into a single decoder -reconstructing the image.

-

Additionally, two classifiers are trained, predicting the domain and class label -from the respective latent variable, emphasizing to capture these information in this variables. -This leads to an overall large network. However, during inference only the class encoder and classifier -is used. The experiments are showing that it is indeed possible to disentangle the information in their -test setting.

-

Also in a semi-supervised setting, where class labels are missing for some data or domains, -the classification accuracy can be further improved. This is an advantage in the sense that prediction -accuracy turns out to be notably better if the training contained a domain close to the test domain. -Therefore, this semi-supervised setup allows to prepare for new domains by some additional training -needing only samples of the new domain, but no class labels. In the end however, DIVA always needs domain -labels and does not support a fully unsupervised setting. Since it is not always clear what different domains -actually exist, this can lead to problems and decreased performance.

-

Model parameters: -the following model parameters can be specified:

-
    -
  • Size of latent space for domain-specific information: zd_dim

  • -
  • Size of latent space for residual variance: zx_dim

  • -
  • Size of latent space for class-specific information: zy_dim

  • -
  • Multiplier for y classifier (\(\alpha_y\) of eq. (2) in paper below): gamma_y

  • -
  • Multiplier for d classifier (\(\alpha_d\) of eq. (2) in paper below): gamma_d

  • -
-

Reference: -DIVA: Domain Invariant Variational Autoencoders, https://arxiv.org/pdf/1905.10427.pdf, Medical Imaging with Deep Learning. PMLR, 2020.

-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/doc_diva.md b/docs/build/html/doc_diva.md deleted file mode 100644 index 14ddcaa38..000000000 --- a/docs/build/html/doc_diva.md +++ /dev/null @@ -1,39 +0,0 @@ -# DIVA: Domain Invariant Variational Autoencoders - -DIVA approaches the domain generalization problem with a variational autoencoder -with three latent variables, using three independent encoders. - -By encouraging the network to store the domain, -class and residual features in one of the latent space respectively the class specific information -shall be disentangled. - -In order to obtain marginally independent latent variables, the density of the domain -and class latent space is conditioned on the domain and class respectively. These densities are parameterized -by learnable parameters. During training, all three latent variables are then fed into a single decoder -reconstructing the image. - -Additionally, two classifiers are trained, predicting the domain and class label -from the respective latent variable, emphasizing to capture these information in this variables. -This leads to an overall large network. However, during inference only the class encoder and classifier -is used. The experiments are showing that it is indeed possible to disentangle the information in their -test setting. - -Also in a semi-supervised setting, where class labels are missing for some data or domains, -the classification accuracy can be further improved. This is an advantage in the sense that prediction -accuracy turns out to be notably better if the training contained a domain close to the test domain. -Therefore, this semi-supervised setup allows to prepare for new domains by some additional training -needing only samples of the new domain, but no class labels. In the end however, DIVA always needs domain -labels and does not support a fully unsupervised setting. Since it is not always clear what different domains -actually exist, this can lead to problems and decreased performance. - -**Model parameters:** -the following model parameters can be specified: - -- Size of latent space for domain-specific information: zd_dim -- Size of latent space for residual variance: zx_dim -- Size of latent space for class-specific information: zy_dim -- Multiplier for y classifier ($\alpha_y$ of eq. (2) in paper below): gamma_y -- Multiplier for d classifier ($\alpha_d$ of eq. (2) in paper below): gamma_d - -_Reference:_ -DIVA: Domain Invariant Variational Autoencoders, https://arxiv.org/pdf/1905.10427.pdf, Medical Imaging with Deep Learning. PMLR, 2020. diff --git a/docs/build/html/doc_examples.html b/docs/build/html/doc_examples.html deleted file mode 100644 index 11d78efe3..000000000 --- a/docs/build/html/doc_examples.html +++ /dev/null @@ -1,564 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Examples — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

Examples

-
-

Colored version of MNIST

-
-

leave one domain out

-
python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5
-
-
-
-
-

choose train and test

-
python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-

make a sanity check for the dataset using 8 instances from each domain and from each class

-
python main_out.py --te_d=0 --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 --san_check --san_num=4
-
-
-
-
-

generation of images

-
python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 --gen
-
-
-
-
-

use hduva on color mnist, train on 2 domains

-
python main_out.py --tr_d 0 1 2 --te_d 3 --bs=2 --task=mnistcolor10 --aname=hduva  --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2
-
-
-
-
-

hduva is domain-unsupervised, so it works also with a single domain

-
python main_out.py --tr_d 0  --te_d 3 4 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2
-
-
-
-
-
-

Larger images:

-
-

model diva with implemented neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-

model diva with custom neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --npath=examples/nets/resnet.py --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-

model deepall with implemented neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --nname=alexnet
-
-
-
-
-

model dann with implemented neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=dann --nname=alexnet
-
-
-
-
-

model jigen with implemented neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=jigen --nname=alexnet --pperm=1 --nperm=100 --grid_len=3
-
-
-
-
-

model matchdg with implemented neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --nname=alexnet
-
-
-
-
-

hduva with implemented neural network

-
python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2
-
-
-
-
-

hduva use alex net

-
python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=alexnet
-
-
-
-
-
-

Custom Neural Network

-
-

model deepall with custom neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py
-
-
-
-
-

model matchdg with custom neural network

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py
-
-
-
-
-

hduva use custom net for sandwich encoder

-
python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --npath_encoder_sandwich_layer_img2h4zd=examples/nets/resnet.py
-
-
-
-
-

hduva use custom net for topic encoder

-
python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --npath_topic_distrib_img2topic=examples/nets/resnet.py --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2
-
-
-
-
-

hduva use custom net for classification encoder

-
python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --npath=examples/nets/resnet.py --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2
-
-
-
-
-
-

User defined tasks

-
-

Folder Task

-
-

Folder Task with implemented neural network

-
python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-

Folder Task with externally user defined neural network

-
python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-
-

ImagePath Task

-
-

ImagePath Task with implemented algorithm

-
python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-

ImagePath Task with externally user defined neural network

-
python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5
-
-
-
-
-
-
-

Custom algorithm defined in external python file

-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet
-
-
-
python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py
-
-
-
-
-

Adversarial images training

-
python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=deepall_dial --nname=conv_bn_pool_2
-
-
-
-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/doc_examples.md b/docs/build/html/doc_examples.md deleted file mode 100755 index e48424822..000000000 --- a/docs/build/html/doc_examples.md +++ /dev/null @@ -1,143 +0,0 @@ -# Examples - -## Colored version of MNIST - -### leave one domain out -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 -``` - -### choose train and test -``` -python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5 -``` - -### make a sanity check for the dataset using 8 instances from each domain and from each class -``` -python main_out.py --te_d=0 --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 --san_check --san_num=4 -``` - -### generation of images -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 --gen -``` - -### use hduva on color mnist, train on 2 domains -``` -python main_out.py --tr_d 0 1 2 --te_d 3 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - -### hduva is domain-unsupervised, so it works also with a single domain -``` -python main_out.py --tr_d 0 --te_d 3 4 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - - -## Larger images: - -### model diva with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -### model diva with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --npath=examples/nets/resnet.py --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -### model deepall with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --nname=alexnet -``` - -### model dann with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=dann --nname=alexnet -``` - -### model jigen with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=jigen --nname=alexnet --pperm=1 --nperm=100 --grid_len=3 -``` - -### model matchdg with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --nname=alexnet -``` - -### hduva with implemented neural network -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - -### hduva use alex net -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=alexnet -``` - - -## Custom Neural Network - -### model deepall with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py -``` - -### model matchdg with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py -``` - -### hduva use custom net for sandwich encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --npath_encoder_sandwich_layer_img2h4zd=examples/nets/resnet.py -``` - -### hduva use custom net for topic encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --npath_topic_distrib_img2topic=examples/nets/resnet.py --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - -### hduva use custom net for classification encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --npath=examples/nets/resnet.py --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 -``` - - -## User defined tasks - -### Folder Task -#### Folder Task with implemented neural network -``` -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 -``` - -#### Folder Task with externally user defined neural network -``` -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -### ImagePath Task -#### ImagePath Task with implemented algorithm -``` -python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 -``` - -#### ImagePath Task with externally user defined neural network -``` -python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 -``` - -## Custom algorithm defined in external python file -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet -``` - -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py -``` - -## Adversarial images training -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=deepall_dial --nname=conv_bn_pool_2 -``` diff --git a/docs/build/html/doc_extend_contribute.html b/docs/build/html/doc_extend_contribute.html deleted file mode 100644 index a7ea071d9..000000000 --- a/docs/build/html/doc_extend_contribute.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Extend or contribute with a custom domain generalization algorithm — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

Extend or contribute with a custom domain generalization algorithm

-
-

External extension by implementing your custom models

-

Look at this example

-
cd ..
-python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet
-
-python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py
-
-
-

where the example python file corresponding to --apath defines a model which contains several modules that can be customized to different neural networks via --npath_argna2val if the neural network is specified in a python file -or nname_argna2val if the neural network is already implemented.

-
-
-

Internal extension for more advanced contribution

-
    -
  • implement domainlab/algos/builder_your-algorithm-name.py

  • -
  • add your algorithm into domainlab/algos/zoo_algos.py by adding chain = NodeAlgoBuilder[your-algorithm-name](chain)

  • -
  • note that all algorithms will be converted to lower case!

  • -
  • make a pull request

  • -
-
-

Design

-

Design Diagram

-
-
-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/doc_extend_contribute.md b/docs/build/html/doc_extend_contribute.md deleted file mode 100644 index 245ca50b3..000000000 --- a/docs/build/html/doc_extend_contribute.md +++ /dev/null @@ -1,25 +0,0 @@ -# Extend or contribute with a custom domain generalization algorithm - -## External extension by implementing your custom models - -Look at this example - -``` -cd .. -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet - -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py -``` - -where the example python file corresponding to `--apath` defines a model which contains several modules that can be customized to different neural networks via `--npath_argna2val` if the neural network is specified in a python file -or `nname_argna2val` if the neural network is already implemented. - -## Internal extension for more advanced contribution -- implement `domainlab/algos/builder_your-algorithm-name.py` -- add your algorithm into `domainlab/algos/zoo_algos.py` by adding `chain = NodeAlgoBuilder[your-algorithm-name](chain)` -- note that all algorithms will be converted to lower case! -- make a pull request - - -### Design -![Design Diagram](libDG.svg) diff --git a/docs/build/html/doc_output.html b/docs/build/html/doc_output.html deleted file mode 100644 index fb5879273..000000000 --- a/docs/build/html/doc_output.html +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Output structure — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -
-

Output structure

-

By default, this package generates outputs into a folder zoutput relative to the current working directory, which the user can alter by specifying the corresponding command line argument.

-

The output structure is something similar to below. ([] means the folder might or might not exist, texts inside () are comments)

-
zoutput/
-├── aggrsts (aggregation of results)
-│   ├── task1_test_domain1_tagName.csv
-│   ├── task2_test_domain3_tagName.csv
-│   
-│  
-├── [gen] (counterfactual image generation, only exist for generative models with "--gen" specified)
-│   ├── [task1_test_domain1]
-│   
-└── saved_models (persisted pytorch model)
-    ├── task1_algo1_git-commit-hashtag1_seed_1_instance_wise_predictions.txt (instance wise prediction of the model)
-    ├── [task1_algo1_git-commit-hashtag1_seed_1.model]  (only exist if with command line argument "--keep_model")
-    ...
-
-
-

aggrst folder is aggregating results from several runs corresponding to the same train test split of the identical task, that means after each run, an extra line will be appended to the file corresponding to the same train test split of the identical task, so that it is convenient to compare between different algorithms and configurations upon the same train test split of the identical task.

-

saved_models folder contains instance wise prediction in a text file for each run, and potentially the persisted model on the hard disk (by default, these models will be deleted after run is completed).

-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/doc_output.md b/docs/build/html/doc_output.md deleted file mode 100644 index 61c67e17a..000000000 --- a/docs/build/html/doc_output.md +++ /dev/null @@ -1,25 +0,0 @@ -# Output structure - -By default, this package generates outputs into a folder `zoutput` relative to the current working directory, which the user can alter by specifying the corresponding command line argument. - -The output structure is something similar to below. ([] means the folder might or might not exist, texts inside () are comments) - -``` -zoutput/ -├── aggrsts (aggregation of results) -│ ├── task1_test_domain1_tagName.csv -│ ├── task2_test_domain3_tagName.csv -│ -│ -├── [gen] (counterfactual image generation, only exist for generative models with "--gen" specified) -│ ├── [task1_test_domain1] -│ -└── saved_models (persisted pytorch model) - ├── task1_algo1_git-commit-hashtag1_seed_1_instance_wise_predictions.txt (instance wise prediction of the model) - ├── [task1_algo1_git-commit-hashtag1_seed_1.model] (only exist if with command line argument "--keep_model") - ... -``` - -`aggrst` folder is aggregating results from several runs corresponding to the same train test split of the identical task, that means after each run, an extra line will be appended to the file corresponding to the same train test split of the identical task, so that it is convenient to compare between different algorithms and configurations upon the same train test split of the identical task. - -`saved_models` folder contains instance wise prediction in a text file for each run, and potentially the persisted model on the hard disk (by default, these models will be deleted after run is completed). diff --git a/docs/build/html/doc_tasks.html b/docs/build/html/doc_tasks.html deleted file mode 100644 index 0308b5c78..000000000 --- a/docs/build/html/doc_tasks.html +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Task Specification — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
- -
- -
-
- -
-

Task Specification

-

The package offers various ways to specify the domain generalization task according to user’s need.

-
-

TaskPathList

-

The user need to provide a python file indicating the root directories where images (data) from each domain are located, and for each domain, the user shall provide a plain text file indicating the file names.

-

An example python file can be found in the examples directory of the repository with the corresponding data be found at the data directory of the repository, where the text file indicating which file correspond to which class label (starting from 1) can be found at example text file. -The user should specify the location of the python file via command line arguments --tpath

-
-
-

TaskFolder

-

In this mode, we assume there are structured folders where each folder contains all data from one domain, and each domain folder contains subfolders corresponding to different classes. See examples below.

-
-

Data organization

-

To give an example, suppose we have a classification task to classify between car, dog, human, chair and bird and there are 3 data sources (domains) with folder name “folder_a”, “folder_b” and “folder_c” respectively as shown below.

-

In each folder, the images are organized in sub-folders by their class. For example, “/path/to/3rd_domain/folder_c/dog” folder contains all the images of class “dog” from the 3rd domain.

-

It might be the case that across the different data sources the same class is named differently. For example, in the 1st data source, the class dog is stored in sub-folder named -“hund”, in the 2nd data source, the dog is stored in sub-folder named “husky” and in the 3rd data source, the dog is stored in sub-folder named “dog”.

-

It might also be the case that some classes exist in one data source but does not exist in another data source. For example, folder “/path/to/2nd_domain/folder_b” does not have a sub-folder for class “human”.

-

Folder structure of the 1st domain:

-
    ── /path/to/1st_domain/folder_a
-       ├── auto
-       ├── hund
-       ├── mensch
-       ├── stuhl
-       └── vogel
-    
-
-
-

Folder structure of the 2nd domain:

-
    ── /path/to/2nd_domain/folder_b
-       ├── bird
-       ├── drive
-       ├── sit
-       └── husky
-
-
-

Folder structure of the 3rd domain:

-
    ── /path/to/3rd_domain/folder_c
-        ├── dog
-        ├── flying
-        ├── sapiens
-        ├── sofa
-        └── vehicle
-
-
-
-
-

Specify the task with domainlab API

-

The user is expected to implement something similar to the following code in a separate python file with a function with signature get_task(na=None).

-
import os
-from torchvision import transforms
-
-from domainlab.tasks import mk_task_folder, ImSize
-
-# specify torchvision transformations for training
-trans_tr = transforms.Compose([
-    transforms.Resize((224, 224)),
-    transforms.RandomResizedCrop(224, scale=(0.7, 1.0)),
-    transforms.RandomHorizontalFlip(),
-    transforms.ColorJitter(0.3, 0.3, 0.3, 0.3),
-    transforms.RandomGrayscale(),
-    transforms.ToTensor(),
-    transforms.Normalize([0.485, 0.456, 0.406],
-                         [0.229, 0.224, 0.225])
-])
-
-# specify torchvision transformations at test/inference time
-trans_te = transforms.Compose([
-    transforms.Resize((224, 224)),
-    transforms.ToTensor(),
-    transforms.Normalize([0.485, 0.456, 0.406],
-                         [0.229, 0.224, 0.225])
-])
-
-
-chain = mk_task_folder(extensions={"domain1": "jpg", "domain2": "jpg", "domain3": "jpg"},
-                       list_str_y=["chair", "car"],
-                       dict_domain_folder_name2class={
-                           "domain1": {"auto": "car", "stuhl": "chair"},
-                           "domain2": {"vehicle": "car", "sofa": "chair"},
-                           "domain3": {"drive": "car", "sit": "chair"}
-                       },
-                       dict_domain_img_trans={
-                           "domain1": trans_tr,
-                           "domain2": trans_tr,
-                           "domain3": trans_tr,
-                       },
-                       img_trans_te=trans_te,
-                       isize=ImSize(3, 224, 224),
-                       dict_domain2imgroot={
-                           "domain1": os.path.join("/path/to/1st_domain", "folder_a"),
-                           "domain2": os.path.join("/path/to/2nd_domain", "folder_b"),
-                           "domain3": os.path.join("/path/to/3rd_domain", "folder_c")},
-                       taskna="task_demo")
-
-def get_task(na=None):  # the package will call this function to get the task
-    return chain
-
-
-

The domainlab function to create task in this example is domainlab.tasks.mk_task_folder

-
from domainlab.tasks import mk_task_folder
-print(mk_task_folder.__doc__)
-
-extensions: a python dictionary with key as the domain name
-and value as the file extensions of the image.
-
-list_str_y: a python list with user defined class names where
-the order of the list matters.
-
-dict_domain_folder_name2class: a python dictionary, with key
-as the user specified domain name, value as a dictionary to map the
-sub-folder name of each domain's class folder into the user defined
-common class name.
-
-dict_domain_img_trans: a python dictionary with keys as the user
-specified domain name, value as a user defined torchvision transform.
-This feature allows carrying out different transformation (composition) to different
-domains at training time.
-
-img_trans_te: at test or inference time, we do not have knowledge
-of domain information so only a unique transform (composition) is allowed.
-
-isize: domainlab.tasks.ImSize(image channel, image height, image width)
-
-dict_domain2imgroot: a python dictionary with keys as user specified domain names and values 
-as the absolute path to each domain's data.
-
-taskna: user defined task name
-
-
-
-
-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/doc_tasks.md b/docs/build/html/doc_tasks.md deleted file mode 100644 index fcbf7110d..000000000 --- a/docs/build/html/doc_tasks.md +++ /dev/null @@ -1,136 +0,0 @@ -# Task Specification - -The package offers various ways to specify the domain generalization task according to user's need. - -## TaskPathList -The user need to provide a python file indicating the root directories where images (data) from each domain are located, and for each domain, the user shall provide a plain text file indicating the file names. - -An example python file can be found in the [examples directory of the repository](https://github.com/marrlab/DomainLab/blob/master/examples/tasks/demo_task_path_list_small.py) with the corresponding data be found at [the data directory of the repository](https://github.com/marrlab/DomainLab/tree/master/data), where the text file indicating which file correspond to which class label (starting from 1) can be found at [example text file](https://github.com/marrlab/DomainLab/blob/master/data/pacs_split/art_painting_10.txt). -The user should specify the location of the python file via command line arguments `--tpath` - -## TaskFolder -In this mode, we assume there are structured folders where each folder contains all data from one domain, and each domain folder contains subfolders corresponding to different classes. See examples below. - -### Data organization -To give an example, suppose we have a classification task to classify between car, dog, human, chair and bird and there are 3 data sources (domains) with folder name "folder_a", "folder_b" and "folder_c" respectively as shown below. - -In each folder, the images are organized in sub-folders by their class. For example, "/path/to/3rd_domain/folder_c/dog" folder contains all the images of class "dog" from the 3rd domain. - -It might be the case that across the different data sources the same class is named differently. For example, in the 1st data source, the class dog is stored in sub-folder named -"hund", in the 2nd data source, the dog is stored in sub-folder named "husky" and in the 3rd data source, the dog is stored in sub-folder named "dog". - -It might also be the case that some classes exist in one data source but does not exist in another data source. For example, folder "/path/to/2nd_domain/folder_b" does not have a sub-folder for class "human". - -Folder structure of the 1st domain: -``` - ── /path/to/1st_domain/folder_a - ├── auto - ├── hund - ├── mensch - ├── stuhl - └── vogel - -``` -Folder structure of the 2nd domain: - -``` - ── /path/to/2nd_domain/folder_b - ├── bird - ├── drive - ├── sit - └── husky -``` -Folder structure of the 3rd domain: - -``` - ── /path/to/3rd_domain/folder_c - ├── dog - ├── flying - ├── sapiens - ├── sofa - └── vehicle -``` - -### Specify the task with domainlab API -The user is expected to implement something similar to the following code in a separate python file with a function with signature `get_task(na=None)`. -``` -import os -from torchvision import transforms - -from domainlab.tasks import mk_task_folder, ImSize - -# specify torchvision transformations for training -trans_tr = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.RandomResizedCrop(224, scale=(0.7, 1.0)), - transforms.RandomHorizontalFlip(), - transforms.ColorJitter(0.3, 0.3, 0.3, 0.3), - transforms.RandomGrayscale(), - transforms.ToTensor(), - transforms.Normalize([0.485, 0.456, 0.406], - [0.229, 0.224, 0.225]) -]) - -# specify torchvision transformations at test/inference time -trans_te = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.ToTensor(), - transforms.Normalize([0.485, 0.456, 0.406], - [0.229, 0.224, 0.225]) -]) - - -chain = mk_task_folder(extensions={"domain1": "jpg", "domain2": "jpg", "domain3": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "domain1": {"auto": "car", "stuhl": "chair"}, - "domain2": {"vehicle": "car", "sofa": "chair"}, - "domain3": {"drive": "car", "sit": "chair"} - }, - dict_domain_img_trans={ - "domain1": trans_tr, - "domain2": trans_tr, - "domain3": trans_tr, - }, - img_trans_te=trans_te, - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "domain1": os.path.join("/path/to/1st_domain", "folder_a"), - "domain2": os.path.join("/path/to/2nd_domain", "folder_b"), - "domain3": os.path.join("/path/to/3rd_domain", "folder_c")}, - taskna="task_demo") - -def get_task(na=None): # the package will call this function to get the task - return chain -``` -The domainlab function to create task in this example is `domainlab.tasks.mk_task_folder` -``` -from domainlab.tasks import mk_task_folder -print(mk_task_folder.__doc__) - -extensions: a python dictionary with key as the domain name -and value as the file extensions of the image. - -list_str_y: a python list with user defined class names where -the order of the list matters. - -dict_domain_folder_name2class: a python dictionary, with key -as the user specified domain name, value as a dictionary to map the -sub-folder name of each domain's class folder into the user defined -common class name. - -dict_domain_img_trans: a python dictionary with keys as the user -specified domain name, value as a user defined torchvision transform. -This feature allows carrying out different transformation (composition) to different -domains at training time. - -img_trans_te: at test or inference time, we do not have knowledge -of domain information so only a unique transform (composition) is allowed. - -isize: domainlab.tasks.ImSize(image channel, image height, image width) - -dict_domain2imgroot: a python dictionary with keys as user specified domain names and values -as the absolute path to each domain's data. - -taskna: user defined task name -``` diff --git a/docs/build/html/domainlab.algos.compos.html b/docs/build/html/domainlab.algos.compos.html deleted file mode 100644 index bce2cbd13..000000000 --- a/docs/build/html/domainlab.algos.compos.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.compos package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.algos.compos package

-
-

Submodules

-
-
-

domainlab.algos.compos.matchdg_args module

-
-
-domainlab.algos.compos.matchdg_args.add_args2parser_matchdg(parser)[source]
-
-
-
-

domainlab.algos.compos.matchdg_base module

-
-
-class domainlab.algos.compos.matchdg_base.MatchAlgoBase(task, phi, args, device, exp)[source]
-

Bases: object

-
-
-get_opt_sgd()[source]
-
-
-
-init_erm_phase()[source]
-

loade model from disk after training -the ctr(contrastive learning) phase

-
-
-
-mk_match_tensor(epoch)[source]
-

initialize or update match tensor

-
-
-
-save_model_ctr_phase()[source]
-
-
-
-save_model_erm_phase()[source]
-
-
-
-
-domainlab.algos.compos.matchdg_base.get_base_domain_size4match_dg(task)[source]
-

Base domain is a dataset where each class -set come from one of the nominal domains

-
-
-
-

domainlab.algos.compos.matchdg_ctr_erm module

-
-
-class domainlab.algos.compos.matchdg_ctr_erm.MatchCtrErm(task, phi, args, device, exp, flag_erm=False)[source]
-

Bases: MatchAlgoBase

-

Contrastive Learning

-
-
-tr_epoch(epoch)[source]
-

# data in one batch comes from two sources: one part from loader, -# the other part from match tensor

-
-
-
-train()[source]
-
-
-
-
-

domainlab.algos.compos.matchdg_match module

-
-
-class domainlab.algos.compos.matchdg_match.MatchPair(dim_y, i_c, i_h, i_w, bs_match, virtual_ref_dset_size, num_domains_tr, list_tr_domain_size)[source]
-

Bases: object

-
-
-
-

domainlab.algos.compos.matchdg_utils module

-

create dictionary for matching

-
-
-class domainlab.algos.compos.matchdg_utils.MatchDictInit(keys, vals, i_c, i_h, i_w)[source]
-

Bases: object

-

base class for matching dictionary creator

-
-
-get_num_rows(key)[source]
-
-
-
-
-class domainlab.algos.compos.matchdg_utils.MatchDictNumDomain2SizeDomain(num_domains_tr, list_tr_domain_size, i_c, i_h, i_w)[source]
-

Bases: MatchDictInit

-

tensor dimension for the kth domain: [num_domains_tr, (size_domain_k, i_c, i_h, i_w)]

-
-
-get_num_rows(key)[source]
-
-
-
-
-class domainlab.algos.compos.matchdg_utils.MatchDictVirtualRefDset2EachDomain(virtual_ref_dset_size, num_domains_tr, i_c, i_h, i_w)[source]
-

Bases: MatchDictInit

-

dict[0:virtual_ref_dset_size] has tensor dimension: (num_domains_tr, i_c, i_h, i_w)

-
-
-get_num_rows(key=None)[source]
-

key is 0:virtual_ref_dset_size

-
-
-
-
-domainlab.algos.compos.matchdg_utils.dist_cosine_agg(x1, x2)[source]
-

torch.nn.CosineSimilarity assumes x1 and x2 share exactly the same dimension

-
-
-
-domainlab.algos.compos.matchdg_utils.dist_pairwise_cosine(x1, x2, tau=0.05)[source]
-

x1 and x2 does not necesarilly have the same shape, and we want to have a cartesian product of the pairwise distances

-
-
-
-domainlab.algos.compos.matchdg_utils.fun_tensor_normalize(tensor_batch_x)[source]
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.algos.html b/docs/build/html/domainlab.algos.html deleted file mode 100644 index 1938eef91..000000000 --- a/docs/build/html/domainlab.algos.html +++ /dev/null @@ -1,602 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.algos package

-
-

Subpackages

- -
-
-

Submodules

-
-
-

domainlab.algos.a_algo_builder module

-
-
-class domainlab.algos.a_algo_builder.NodeAlgoBuilder(success_node=None)[source]
-

Bases: AbstractChainNodeHandler

-

Base class for Algorithm Builder

-
-
-dset_decoration_args_algo(args, ddset)[source]
-

most algorithms do not need re-organization of data feed flow like JiGen and MatchDG

-
-
-
-init_business(exp)[source]
-

init_business: initialize and return the heavy weight business object for -doing the real job -:param request: subclass can override request object to be string or function -:return: the constructed service object

-
-
-
-is_myjob(request)[source]
-
-
Parameters:
-

request – string

-
-
-
-
-
-na_prefix = 'NodeAlgoBuilder'
-
-
-
-property name
-

get the name of the algorithm

-
-
-
-
-

domainlab.algos.builder_custom module

-
-
-domainlab.algos.builder_custom.make_basic_trainer(class_name_model)[source]
-

make_basic_trainer. -:param class_name_model:

-
-
-
-

domainlab.algos.builder_dann module

-

builder for Domain Adversarial Neural Network: accept different training scheme

-
-
-class domainlab.algos.builder_dann.NodeAlgoBuilderDANN(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.builder_deepall module

-
-
-class domainlab.algos.builder_deepall.NodeAlgoBuilderDeepAll(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.builder_dial module

-

builder for domain invariant adversarial learning

-
-
-class domainlab.algos.builder_dial.NodeAlgoBuilderDeepAll_DIAL(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-

builder for domain invariant adversarial learning

-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.builder_diva module

-

Builder pattern to build different component for experiment with DIVA

-
-
-class domainlab.algos.builder_diva.NodeAlgoBuilderDIVA(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-

Builder pattern to build different component for experiment with DIVA

-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.builder_hduva module

-
-
-class domainlab.algos.builder_hduva.NodeAlgoBuilderHDUVA(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.builder_jigen1 module

-

builder for JiGen

-
-
-class domainlab.algos.builder_jigen1.NodeAlgoBuilderJiGen(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-
-
-dset_decoration_args_algo(args, ddset)[source]
-

JiGen need to shuffle the tiles of the original image

-
-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.builder_matchdg module

-
-
-class domainlab.algos.builder_matchdg.NodeAlgoBuilderMatchDG(success_node=None)[source]
-

Bases: NodeAlgoBuilder

-

algorithm builder for matchDG

-
-
-dset_decoration_args_algo(args, ddset)[source]
-

most algorithms do not need re-organization of data feed flow like JiGen and MatchDG

-
-
-
-init_business(exp)[source]
-

return trainer, model, observer

-
-
-
-
-

domainlab.algos.zoo_algos module

-
-
-class domainlab.algos.zoo_algos.AlgoBuilderChainNodeGetter(args)[source]
-

Bases: object

-

1. Hardcoded chain -3. Return selected node

-
-
-register_external_node(chain)[source]
-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.algos.msels.html b/docs/build/html/domainlab.algos.msels.html deleted file mode 100644 index 99ddc0c9e..000000000 --- a/docs/build/html/domainlab.algos.msels.html +++ /dev/null @@ -1,445 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.msels package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.algos.msels package

-
-

Submodules

-
-
-

domainlab.algos.msels.a_model_sel module

-
-
-class domainlab.algos.msels.a_model_sel.AMSel[source]
-

Bases: object

-
-
-accept(trainer, tr_obs)[source]
-

Visitor pattern to trainer

-
-
-
-if_stop()[source]
-

check if trainer should stop

-
-
-
-abstract update()[source]
-

observer + visitor pattern to trainer

-
-
-
-
-

domainlab.algos.msels.c_msel module

-

Model Selection should be decoupled from

-
-
-class domainlab.algos.msels.c_msel.MSelTrLoss(max_es)[source]
-

Bases: AMSel

-
    -
  1. Model selection using sum of loss across training domains

  2. -
  3. Visitor pattern to trainer

  4. -
-
-
-if_stop()[source]
-

if should early stop

-
-
-
-update()[source]
-

if the best model should be updated

-
-
-
-
-

domainlab.algos.msels.c_msel_oracle module

-

Model Selection should be decoupled from

-
-
-class domainlab.algos.msels.c_msel_oracle.MSelOracleVisitor(msel)[source]
-

Bases: AMSel

-

save best out-of-domain test acc model, but do not affect -how the final model is selected

-
-
-accept(trainer, tr_obs)[source]
-

Visitor pattern to trainer

-
-
-
-if_stop()[source]
-

if should early stop -oracle model selection does not intervene how models get selected -by the innermost model selection

-
-
-
-update()[source]
-

if the best model should be updated

-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.algos.observers.html b/docs/build/html/domainlab.algos.observers.html deleted file mode 100644 index d162423eb..000000000 --- a/docs/build/html/domainlab.algos.observers.html +++ /dev/null @@ -1,475 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.observers package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.algos.observers package

-
-

Submodules

-
-
-

domainlab.algos.observers.a_observer module

-

interface for observer + visitor

-
-
-class domainlab.algos.observers.a_observer.AObVisitor[source]
-

Bases: object

-

Observer + Visitor pattern for model selection

-
-
-abstract accept(trainer)[source]
-

accept invitation as a visitor

-
-
-
-abstract after_all()[source]
-

After training is done

-
-
-
-abstract clean_up()[source]
-

to be called by a decorator

-
-
-
-abstract update(epoch)[source]
-

return True/False whether the trainer should stop training

-
-
-
-
-

domainlab.algos.observers.b_obvisitor module

-
-
-class domainlab.algos.observers.b_obvisitor.ObVisitor(exp, model_sel, device)[source]
-

Bases: AObVisitor

-

Observer + Visitor pattern for model selection

-
-
-accept(trainer)[source]
-

accept invitation as a visitor

-
-
-
-after_all()[source]
-

After training is done

-
-
-
-clean_up()[source]
-

to be called by a decorator

-
-
-
-update(epoch)[source]
-

return True/False whether the trainer should stop training

-
-
-
-
-

domainlab.algos.observers.c_obvisitor_cleanup module

-
-
-class domainlab.algos.observers.c_obvisitor_cleanup.ObVisitorCleanUp(observer)[source]
-

Bases: AObVisitor

-

decorator of observer

-
-
-accept(trainer)[source]
-

accept invitation as a visitor

-
-
-
-after_all()[source]
-

After training is done

-
-
-
-clean_up()[source]
-

to be called by a decorator

-
-
-
-update(epoch)[source]
-

return True/False whether the trainer should stop training

-
-
-
-
-

domainlab.algos.observers.c_obvisitor_gen module

-
-
-class domainlab.algos.observers.c_obvisitor_gen.ObVisitorGen(exp, model_sel, device)[source]
-

Bases: ObVisitor

-

For Generative Models

-
-
-after_all()[source]
-

After training is done

-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.algos.trainers.html b/docs/build/html/domainlab.algos.trainers.html deleted file mode 100644 index 82059c5ed..000000000 --- a/docs/build/html/domainlab.algos.trainers.html +++ /dev/null @@ -1,575 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.algos.trainers package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.algos.trainers package

-
-

Submodules

-
-
-

domainlab.algos.trainers.a_trainer module

-

Base Class for trainer

-
-
-class domainlab.algos.trainers.a_trainer.AbstractTrainer(model, task, observer, device, aconf)[source]
-

Bases: object

-

Algorithm director that controls the data flow

-
-
-after_batch(epoch, ind_batch)[source]
-
-
Parameters:
-
    -
  • epoch

  • -
  • ind_batch

  • -
-
-
-
-
-
-abstract before_tr()[source]
-

before training, probe model performance

-
-
-
-post_tr()[source]
-

after training

-
-
-
-abstract tr_epoch(epoch)[source]
-
-
Parameters:
-

epoch

-
-
-
-
-
-
-

domainlab.algos.trainers.args_dial module

-

domain invariant adversarial trainer hyper-parmaeters

-
-
-domainlab.algos.trainers.args_dial.add_args2parser_dial(parser)[source]
-

append hyper-parameters to the main argparser

-
-
-
-

domainlab.algos.trainers.train_basic module

-

basic trainer

-
-
-class domainlab.algos.trainers.train_basic.TrainerBasic(model, task, observer, device, aconf)[source]
-

Bases: AbstractTrainer

-

basic trainer

-
-
-before_tr()[source]
-

check the performance of randomly initialized weight

-
-
-
-tr_epoch(epoch)[source]
-
-
Parameters:
-

epoch

-
-
-
-
-
-
-

domainlab.algos.trainers.train_dial module

-

use random start to generate adversarial images

-
-
-class domainlab.algos.trainers.train_dial.TrainerDIAL(model, task, observer, device, aconf)[source]
-

Bases: TrainerBasic

-

Trainer Domain Invariant Adversarial Learning

-
-
-gen_adversarial(device, img_natural, vec_y)[source]
-

use naive trimming to find optimize img in the direction of adversarial gradient, -this is not necessarily constraint optimal due to nonlinearity, -as the constraint epsilon is only considered ad-hoc

-
-
-
-tr_batch(epoch, ind_batch)[source]
-

anneal parameter for each batch

-
-
-
-tr_epoch(epoch)[source]
-
-
Parameters:
-

epoch

-
-
-
-
-
-
-

domainlab.algos.trainers.train_matchdg module

-
-
-class domainlab.algos.trainers.train_matchdg.TrainerMatchDG(exp, task, ctr_model, model, observer, args, device)[source]
-

Bases: AbstractTrainer

-
-
-before_tr()[source]
-

configure trainer accoding to properties of task as well according to algorithm configs

-
-
-
-tr_epoch(epoch)[source]
-
-
Parameters:
-

epoch

-
-
-
-
-
-
-

domainlab.algos.trainers.train_visitor module

-

update hyper-parameters during training

-
-
-class domainlab.algos.trainers.train_visitor.HyperSchedulerAneal(**kwargs)[source]
-

Bases: HyperSchedulerWarmup

-
-
-aneal(epoch, alpha)[source]
-

start from a small value of par to ramp up the steady state value using -number of total_steps -:param epoch:

-
-
-
-
-class domainlab.algos.trainers.train_visitor.HyperSchedulerWarmup(**kwargs)[source]
-

Bases: object

-
-
-set_steps(total_steps)[source]
-

set number of total_steps to gradually change optimization parameter

-
-
-
-warmup(par_setpoint, epoch)[source]
-

warmup. -start from a small value of par to ramp up the steady state value using -# total_steps -:param epoch:

-
-
-
-
-class domainlab.algos.trainers.train_visitor.TrainerVisitor(model, task, observer, device, aconf)[source]
-

Bases: TrainerBasic

-
-
-after_batch(epoch, ind_batch)[source]
-
-
Parameters:
-
    -
  • epoch

  • -
  • ind_batch

  • -
-
-
-
-
-
-before_tr()[source]
-

check the performance of randomly initialized weight

-
-
-
-set_scheduler(scheduler, total_steps, flag_update_epoch=False, flag_update_batch=False)[source]
-

set the warmup or anealing strategy

-
-
-
-tr_batch(epoch, ind_batch)[source]
-

anneal hyper-parameter for each batch

-
-
-
-tr_epoch(epoch)[source]
-

update hyper-parameters only per epoch

-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.compos.html b/docs/build/html/domainlab.compos.html deleted file mode 100644 index f412799c0..000000000 --- a/docs/build/html/domainlab.compos.html +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.compos package

-
-

Subpackages

- -
-
-

Submodules

-
-
-

domainlab.compos.a_nn_builder module

-

Integrate Chain-of-Responsibility and Builder Pattern for feature extract

-
-
-class domainlab.compos.a_nn_builder.AbstractFeatExtractNNBuilderChainNode(successor_node)[source]
-

Bases: AbstractChainNodeHandler

-

to ensure chain of responsibility node AbstractChainNodeHandler always -work even some node can not start their heavy weight business object, -avoid override the initializer so that node construction is always -light weight.

-
-
-init_business(dim_out, args, i_c=None, i_h=None, i_w=None, flag_pretrain=None, remove_last_layer=False)[source]
-

initialize and return the heavy weight business object for doing -the real job -:param request: subclass can override request object to be string or -function -:return: the constructed service object

-
-
-
-is_myjob(args)[source]
-
-
Parameters:
-

args_nname – command line arguments: -“–nname”: name of the torchvision model -“–npath”: path to the user specified python file with neural -network definition

-
-
-
-
-
-
-

domainlab.compos.builder_nn_alex module

-
-
-domainlab.compos.builder_nn_alex.mkNodeFeatExtractNNBuilderNameAlex(arg_name4net, arg_val)[source]
-
-
-
-

domainlab.compos.builder_nn_conv_bn_relu_2 module

-
-
-domainlab.compos.builder_nn_conv_bn_relu_2.mkNodeFeatExtractNNBuilderNameConvBnRelu2(arg_name4net, arg_val, conv_stride)[source]
-

mkNodeFeatExtractNNBuilderNameConvBnRelu2. -In chain of responsibility selection of neural network, reuse code to add -more possibilities of neural network of the same family. -:param arg_name4net: name of nn in args -:param arg_val: the registered name of the neural network to be added -:param conv_stride: should be 1 for 28*28 images -:param i_c: -:param i_h: -:param i_w:

-
-
-
-

domainlab.compos.builder_nn_external_from_file module

-
-
-domainlab.compos.builder_nn_external_from_file.mkNodeFeatExtractNNBuilderExternFromFile(arg_name_net_path)[source]
-

for each algorithm, there might exist different feature extractors, e.g. -for diva, there can be class feature extractor and domain feature -extractor

-
-
-
-

domainlab.compos.utils_conv_get_flat_dim module

-
-
-domainlab.compos.utils_conv_get_flat_dim.get_flat_dim(module, i_channel, i_h, i_w, batchsize=5)[source]
-

flat the convolution layer output and get the flat dimension for fully -connected network -:param module: -:param i_channel: -:param i_h: -:param i_w: -:param batchsize:

-
-
-
-

domainlab.compos.zoo_nn module

-
-
-class domainlab.compos.zoo_nn.FeatExtractNNBuilderChainNodeGetter(args, arg_name_of_net, arg_path_of_net)[source]
-

Bases: object

-

1. Hardcoded chain -3. Return selected node

-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.compos.nn_zoo.html b/docs/build/html/domainlab.compos.nn_zoo.html deleted file mode 100644 index e884bb532..000000000 --- a/docs/build/html/domainlab.compos.nn_zoo.html +++ /dev/null @@ -1,770 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.compos.nn_zoo package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.compos.nn_zoo package

-
-

Submodules

-
-
-

domainlab.compos.nn_zoo.net_adversarial module

-
-
-class domainlab.compos.nn_zoo.net_adversarial.AutoGradFunMultiply(*args, **kwargs)[source]
-

Bases: Function

-
-
-static backward(ctx, grad_output)[source]
-

Defines a formula for differentiating the operation with backward mode -automatic differentiation (alias to the vjp function).

-

This function is to be overridden by all subclasses.

-

It must accept a context ctx as the first argument, followed by -as many outputs as the forward() returned (None will be passed in -for non tensor outputs of the forward function), -and it should return as many tensors, as there were inputs to -forward(). Each argument is the gradient w.r.t the given output, -and each returned value should be the gradient w.r.t. the -corresponding input. If an input is not a Tensor or is a Tensor not -requiring grads, you can just pass None as a gradient for that input.

-

The context can be used to retrieve tensors saved during the forward -pass. It also has an attribute ctx.needs_input_grad as a tuple -of booleans representing whether each input needs gradient. E.g., -backward() will have ctx.needs_input_grad[0] = True if the -first input to forward() needs gradient computated w.r.t. the -output.

-
-
-
-static forward(ctx, x, alpha)[source]
-

Performs the operation.

-

This function is to be overridden by all subclasses.

-

It must accept a context ctx as the first argument, followed by any -number of arguments (tensors or other types).

-

The context can be used to store arbitrary data that can be then -retrieved during the backward pass. Tensors should not be stored -directly on ctx (though this is not currently enforced for -backward compatibility). Instead, tensors should be saved either with -ctx.save_for_backward() if they are intended to be used in -backward (equivalently, vjp) or ctx.save_for_forward() -if they are intended to be used for in jvp.

-
-
-
-
-class domainlab.compos.nn_zoo.net_adversarial.AutoGradFunReverseMultiply(*args, **kwargs)[source]
-

Bases: Function

-

https://pytorch.org/docs/stable/autograd.html -https://pytorch.org/docs/stable/notes/extending.html#extending-autograd

-
-
-static backward(ctx, grad_output)[source]
-

Defines a formula for differentiating the operation with backward mode -automatic differentiation (alias to the vjp function).

-

This function is to be overridden by all subclasses.

-

It must accept a context ctx as the first argument, followed by -as many outputs as the forward() returned (None will be passed in -for non tensor outputs of the forward function), -and it should return as many tensors, as there were inputs to -forward(). Each argument is the gradient w.r.t the given output, -and each returned value should be the gradient w.r.t. the -corresponding input. If an input is not a Tensor or is a Tensor not -requiring grads, you can just pass None as a gradient for that input.

-

The context can be used to retrieve tensors saved during the forward -pass. It also has an attribute ctx.needs_input_grad as a tuple -of booleans representing whether each input needs gradient. E.g., -backward() will have ctx.needs_input_grad[0] = True if the -first input to forward() needs gradient computated w.r.t. the -output.

-
-
-
-static forward(ctx, x, alpha)[source]
-

Performs the operation.

-

This function is to be overridden by all subclasses.

-

It must accept a context ctx as the first argument, followed by any -number of arguments (tensors or other types).

-

The context can be used to store arbitrary data that can be then -retrieved during the backward pass. Tensors should not be stored -directly on ctx (though this is not currently enforced for -backward compatibility). Instead, tensors should be saved either with -ctx.save_for_backward() if they are intended to be used in -backward (equivalently, vjp) or ctx.save_for_forward() -if they are intended to be used for in jvp.

-
-
-
-
-class domainlab.compos.nn_zoo.net_adversarial.Flatten[source]
-

Bases: Module

-
-
-forward(x)[source]
-

Defines the computation performed at every call.

-

Should be overridden by all subclasses.

-
-

Note

-

Although the recipe for forward pass needs to be defined within -this function, one should call the Module instance afterwards -instead of this since the former takes care of running the -registered hooks while the latter silently ignores them.

-
-
-
-
-training: bool
-
-
-
-
-

domainlab.compos.nn_zoo.net_classif module

-

Classifier

-
-
-class domainlab.compos.nn_zoo.net_classif.ClassifDropoutReluLinear(z_dim, target_dim)[source]
-

Bases: Module

-

first apply dropout, then relu, then linearly fully connected, without activation

-
-
-forward(z_vec)[source]
-
-
Parameters:
-

z_vec

-
-
-
-
-
-training: bool
-
-
-
-
-

domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 module

-

In PyTorch, images are represented as [channels, height, width]

-
-
-class domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2.NetConvBnReluPool2L(i_c, i_h, i_w, conv_stride, dim_out_h)[source]
-

Bases: Module

-
-
-forward(tensor_x)[source]
-
-
Parameters:
-

tensor_x – image

-
-
-
-
-
-training: bool
-
-
-
-
-class domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2.NetConvDense(i_c, i_h, i_w, conv_stride, dim_out_h, args, dense_layer=None)[source]
-

Bases: Module

-
    -
  • For direct topic inference

  • -
  • For custom deep_all, which is extracting the path of VAE from encoder -until classifier. note in encoder, there is extra layer of hidden to mean -and scale, in this component, it is replaced with another hidden layer.

  • -
-
-
-forward(tensor_x)[source]
-
-
Parameters:
-

tensor_x – image

-
-
-
-
-
-training: bool
-
-
-
-
-domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2.mk_conv_bn_relu_pool(i_channel, conv_stride=1, max_pool_stride=2)[source]
-

Convolution, batch norm, maxpool_2d -Convolution with maxpool_2d as last operation -:param i_channel: -:param conv_stride: -:param max_pool_stride:

-
-
-
-

domainlab.compos.nn_zoo.net_gated module

-
-
-class domainlab.compos.nn_zoo.net_gated.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation=1, activation=None, bias=True)[source]
-

Bases: Module

-
-
-forward(x)[source]
-

Defines the computation performed at every call.

-

Should be overridden by all subclasses.

-
-

Note

-

Although the recipe for forward pass needs to be defined within -this function, one should call the Module instance afterwards -instead of this since the former takes care of running the -registered hooks while the latter silently ignores them.

-
-
-
-
-training: bool
-
-
-
-
-class domainlab.compos.nn_zoo.net_gated.GatedConv2d(input_channels, output_channels, kernel_size, stride, padding, dilation=1, activation=None)[source]
-

Bases: Module

-
-
-forward(x)[source]
-

Defines the computation performed at every call.

-

Should be overridden by all subclasses.

-
-

Note

-

Although the recipe for forward pass needs to be defined within -this function, one should call the Module instance afterwards -instead of this since the former takes care of running the -registered hooks while the latter silently ignores them.

-
-
-
-
-training: bool
-
-
-
-
-class domainlab.compos.nn_zoo.net_gated.GatedDense(input_size, output_size, activation=None)[source]
-

Bases: Module

-
-
-forward(x)[source]
-

Defines the computation performed at every call.

-

Should be overridden by all subclasses.

-
-

Note

-

Although the recipe for forward pass needs to be defined within -this function, one should call the Module instance afterwards -instead of this since the former takes care of running the -registered hooks while the latter silently ignores them.

-
-
-
-
-training: bool
-
-
-
-
-

domainlab.compos.nn_zoo.nn module

-
-
-class domainlab.compos.nn_zoo.nn.DenseNet(input_flat_size, out_hidden_size=1024, last_feat_dim=4096, p_dropout=0.5)[source]
-

Bases: Module

-

(input)-dropout-linear-relu-dropout-linear-relu(output)

-
-
-forward(tensor_x)[source]
-
-
Parameters:
-

x

-
-
-
-
-
-training: bool
-
-
-
-
-class domainlab.compos.nn_zoo.nn.LayerId[source]
-

Bases: Module

-

used to delete layers

-
-
-forward(x)[source]
-
-
Parameters:
-

x

-
-
-
-
-
-training: bool
-
-
-
-
-

domainlab.compos.nn_zoo.nn_alex module

-
-
-class domainlab.compos.nn_zoo.nn_alex.Alex4DeepAll(flag_pretrain, dim_y)[source]
-

Bases: AlexNetBase

-

change the last layer output of AlexNet to the dimension of the

-
-
-training: bool
-
-
-
-
-class domainlab.compos.nn_zoo.nn_alex.AlexNetBase(flag_pretrain)[source]
-

Bases: NetTorchVisionBase

-
AlexNet(
-(features): Sequential(
-    (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2))
-    (1): ReLU(inplace=True)
-    (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
-    (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
-    (4): ReLU(inplace=True)
-    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
-    (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
-    (7): ReLU(inplace=True)
-    (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
-    (9): ReLU(inplace=True)
-    (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
-    (11): ReLU(inplace=True)
-    (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
-)
-(avgpool): AdaptiveAvgPool2d(output_size=(6, 6))
-(classifier): Sequential(
-    (0): Dropout(p=0.5, inplace=False)
-    (1): Linear(in_features=9216, out_features=4096, bias=True)
-    (2): ReLU(inplace=True)
-    (3): Dropout(p=0.5, inplace=False)
-    (4): Linear(in_features=4096, out_features=4096, bias=True)
-    (5): ReLU(inplace=True)
-    (6): Linear(in_features=4096, out_features=7, bias=True)
-)
-)
-
-
-
-
-fetch_net(flag_pretrain)[source]
-
-
-
-training: bool
-
-
-
-
-class domainlab.compos.nn_zoo.nn_alex.AlexNetNoLastLayer(flag_pretrain)[source]
-

Bases: AlexNetBase

-

Change the last layer of AlexNet with identity layer, -the classifier from VAE can then have the same layer depth as deep_all -model so it is fair for comparison

-
-
-training: bool
-
-
-
-
-

domainlab.compos.nn_zoo.nn_torchvision module

-
-
-class domainlab.compos.nn_zoo.nn_torchvision.NetTorchVisionBase(flag_pretrain)[source]
-

Bases: Module

-

fetch model from torchvision

-
-
-fetch_net(flag_pretrain)[source]
-
-
-
-forward(tensor)[source]
-

delegate forward operation to self.net_torchvision

-
-
-
-show()[source]
-

print out which layer will be optimized

-
-
-
-training: bool
-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.dsets.html b/docs/build/html/domainlab.dsets.html deleted file mode 100644 index 4f0a77b50..000000000 --- a/docs/build/html/domainlab.dsets.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.dsets package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.dsets package

-
-

Submodules

-
-
-

domainlab.dsets.a_dset_mnist_color_rgb_solo module

-

Color MNIST with single color

-
-
-class domainlab.dsets.a_dset_mnist_color_rgb_solo.ADsetMNISTColorRGBSolo(ind_color, path, subset_step=100, color_scheme='both', label_transform=<function mk_fun_label2onehot.<locals>.fun_label2onehot>, list_transforms=None, raw_split='train', flag_rand_color=False)[source]
-

Bases: Dataset

-

Color MNIST with single color -1. nominal domains: color palettes/range/spectrum -2. subdomains: color(foreground, background) -3. structure: each subdomain contains a combination of -foreground+background color

-
-
-abstract get_background_color(ind)[source]
-
-
-
-abstract get_foreground_color(ind)[source]
-
-
-
-abstract get_num_colors()[source]
-
-
-
-
-

domainlab.dsets.dset_img_path_list module

-
-
-class domainlab.dsets.dset_img_path_list.DsetImPathList(root_img, path2filelist, trans_img=None, trans_target=None)[source]
-

Bases: Dataset

-
-
-get_list_tuple_img_label()[source]
-
-
-
-
-

domainlab.dsets.dset_mnist_color_solo_default module

-
-
-class domainlab.dsets.dset_mnist_color_solo_default.DsetMNISTColorSoloDefault(ind_color, path, subset_step=100, color_scheme='both', label_transform=<function mk_fun_label2onehot.<locals>.fun_label2onehot>, list_transforms=None, raw_split='train', flag_rand_color=False)[source]
-

Bases: ADsetMNISTColorRGBSolo

-
-
-get_background_color(ind)[source]
-
-
-
-get_foreground_color(ind)[source]
-
-
-
-get_num_colors()[source]
-
-
-
-property palette
-
-
-
-
-

domainlab.dsets.dset_poly_domains_mnist_color_default module

-

merge several solo-color mnist to form a mixed dataset

-
-
-class domainlab.dsets.dset_poly_domains_mnist_color_default.DsetMNISTColorMix(n_domains, path, color_scheme='both')[source]
-

Bases: Dataset

-

merge several solo-color mnist to form a mixed dataset

-
-
-
-class domainlab.dsets.dset_poly_domains_mnist_color_default.DsetMNISTColorMixNoDomainLabel(n_domains, path, color_scheme='both')[source]
-

Bases: DsetMNISTColorMix

-
-
-
-

domainlab.dsets.dset_subfolder module

-

https://github.com/pytorch/vision/blob/bb5af1d77658133af8be8c9b1a13139722315c3a/torchvision/datasets/folder.py#L93 -https://pytorch.org/vision/stable/_modules/torchvision/datasets/folder.html#DatasetFolder.fetch_img_paths

-
-
-class domainlab.dsets.dset_subfolder.DsetSubFolder(root, loader, list_class_dir, extensions=None, transform=None, target_transform=None, is_valid_file=None)[source]
-

Bases: DatasetFolder

-

Only use user provided class names, ignore the other subfolders -:param list_class_dir: list of class directories to use as classes

-
-
-
-domainlab.dsets.dset_subfolder.fetch_img_paths(path_dir, class_to_idx, extensions=None, is_valid_file=None)[source]
-
-
Parameters:
-
    -
  • path_dir – path to fetch images in string format

  • -
  • class_to_idx – given list of strings as class names

  • -
-
-
-

{classes[i]: i for i in range(len(classes))} -:param extensions: file extensions in fstring format -:param is_valid_file: user provided function to check if the file is valid or not -:return : list_tuple_path_cls_ind: list of tuple, (path of file, class index)

-
-
-
-domainlab.dsets.dset_subfolder.has_file_allowed_extension(filename: str, extensions: Tuple[str, ...]) bool[source]
-

Checks if a file is an allowed extension. -Args: -filename (string): path to a file -extensions (tuple of strings): extensions to consider (lowercase) -Returns: bool: True if the filename ends with one of given extensions

-
-
-
-

domainlab.dsets.utils_color_palette module

-
-
-

domainlab.dsets.utils_data module

-

Utilities for dataset

-
-
-class domainlab.dsets.utils_data.DsetInMemDecorator(dset, name=None)[source]
-

Bases: Dataset

-

fetch all items of a dataset into memory

-
-
-
-domainlab.dsets.utils_data.fun_img_path_loader_default(path)[source]
-

https://discuss.pytorch.org/t/handling-rgba-images/88428/4

-
-
-
-domainlab.dsets.utils_data.mk_fun_label2onehot(dim)[source]
-

function generator -index to onehot

-
-
-
-domainlab.dsets.utils_data.plot_ds(dset, f_name, batchsize=32)[source]
-
-
Parameters:
-
    -
  • dset

  • -
  • f_name

  • -
  • batchsize – batch_size

  • -
-
-
-
-
-
-domainlab.dsets.utils_data.plot_ds_list(ds_list, f_name, batchsize=8, shuffle=False)[source]
-

plot list of datasets, each datasets in one row -:param ds_list: -:param fname: -:param batchsize: -:param shuffle:

-
-
-
-

domainlab.dsets.utils_wrapdset_patches module

-

upon a task, if jigen is chosen as the algorithm, then task’s dataset has to be augmented to -include tile permutation

-
-
-class domainlab.dsets.utils_wrapdset_patches.WrapDsetPatches(dataset, num_perms2classify, prob_no_perm, grid_len, ppath=None, flag_do_not_weave_tiles=False)[source]
-

Bases: Dataset

-

given dataset of images, return permuations of tiles of images re-weaved

-
-
-get_tile(img, ind_tile)[source]
-

assume a square image?

-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.exp_protocol.html b/docs/build/html/domainlab.exp_protocol.html deleted file mode 100644 index e8def62e1..000000000 --- a/docs/build/html/domainlab.exp_protocol.html +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.exp_protocol package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.exp_protocol package

-
-

Submodules

-
-
-

domainlab.exp_protocol.run_experiment module

-

Runs one task for a single hyperparameter sample for each leave-out-domain -and each random seed.

-
-
-domainlab.exp_protocol.run_experiment.apply_dict_to_args(args, data: dict, extend=False, flag_warn=False)[source]
-

Tries to apply the data to the args dict of DomainLab. -Unknown keys are silently ignored as long as -extend is not set. -# FIXME: do we have a test to ensure args dict from -# domainlab really got what is passed from “data” dict?

-
-
-
-domainlab.exp_protocol.run_experiment.load_parameters(file: str, index: int) tuple[source]
-

Loads a single parameter sample -@param file: csv file -@param index: index of hyper-parameter

-
-
-
-domainlab.exp_protocol.run_experiment.run_experiment(config: dict, param_file: str, param_index: int, out_file: str, start_seed=None, misc=None)[source]
-

Runs the experiment several times:

-
-
for test_domain in test_domains:
-
for seed from startseed to endseed:

evaluate the algorithm with test_domain, initialization with seed

-
-
-
-
-
-
Parameters:
-
    -
  • config – dictionary from the benchmark yaml

  • -
  • param_file – path to the csv with the parameter samples

  • -
  • param_index – parameter index that should be covered by this task,

  • -
-
-
-

currently this correspond to the line number in the csv file, or row number -in the resulting pandas dataframe -:param out_file: path to the output csv -:param start_seed: random seed to start for stochastic variations of pytorch -:param misc: optional dictionary of additional parameters, if any.

-

# FIXME: we might want to run the experiment using commandline arguments

-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.html b/docs/build/html/domainlab.html deleted file mode 100644 index 6c58b77b3..000000000 --- a/docs/build/html/domainlab.html +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- -
- -
-
-
- -
-
- -
-
- -
-

domainlab package

-
-

Subpackages

-
- -
-
-
-

Submodules

-
-
-

domainlab.arg_parser module

-

Command line arguments

-
-
-domainlab.arg_parser.mk_parser_main()[source]
-

Args for command line definition

-
-
-
-domainlab.arg_parser.parse_cmd_args()[source]
-

get args from command line

-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.models.html b/docs/build/html/domainlab.models.html deleted file mode 100644 index 5f9e9f876..000000000 --- a/docs/build/html/domainlab.models.html +++ /dev/null @@ -1,748 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.models package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.models package

-
-

Submodules

-
-
-

domainlab.models.a_model module

-

operations that all kinds of models should have

-
-
-class domainlab.models.a_model.AModel[source]
-

Bases: Module

-

operations that all models (classification, segmentation, seq2seq)

-
-
-cal_loss(tensor_x, tensor_y, tensor_d, others=None)[source]
-

calculate the loss

-
-
-
-abstract cal_reg_loss(tensor_x, tensor_y, tensor_d, others=None)[source]
-

task independent regularization loss for domain generalization

-
-
-
-abstract cal_task_loss(tensor_x, tensor_y)[source]
-

Calculate the task loss

-
-
Parameters:
-
    -
  • tensor_x – input

  • -
  • tensor_y – label

  • -
-
-
Returns:
-

task loss

-
-
-
-
-
-forward(tensor_x, tensor_y, tensor_d, others=None)[source]
-

forward.

-
-
Parameters:
-
    -
  • x

  • -
  • y

  • -
  • d

  • -
-
-
-
-
-
-training: bool
-
-
-
-
-

domainlab.models.a_model_classif module

-

operations that all claasification model should have

-
-
-class domainlab.models.a_model_classif.AModelClassif(list_str_y, list_d_tr=None)[source]
-

Bases: AModel

-

operations that all classification model should have

-
-
-abstract cal_logit_y(tensor_x)[source]
-

calculate the logit for softmax classification

-
-
-
-cal_loss_gen_adv(x_natural, x_adv, vec_y)[source]
-

calculate loss function for generation of adversarial images

-
-
-
-cal_perf_metric(loader_tr, device, loader_te=None)[source]
-

classification performance matric

-
-
-
-cal_reg_loss(tensor_x, tensor_y, tensor_d, others=None)[source]
-

task independent regularization loss for domain generalization

-
-
-
-cal_task_loss(tensor_x, tensor_y)[source]
-

Calculate the task loss. Used within the cal_loss methods of models -that are subclasses of AModelClassif. Cross entropy loss for -classification is used here by default but could be modified by -subclasses -as necessary.

-
-
Parameters:
-
    -
  • tensor_x – input

  • -
  • tensor_y – label

  • -
-
-
Returns:
-

task loss

-
-
-
-
-
-create_perf_obj(task)[source]
-

for classification, dimension of target can be quieried from task

-
-
-
-property dim_y
-

the class embedding dimension

-
-
-
-evaluate(loader_te, device)[source]
-

for classification task, use the current model to cal acc

-
-
-
-infer_y_vpicn(tensor)[source]
-
-
Parameters:
-

tensor – input

-
-
Returns:
-

vpicn -v: vector of one-hot class label, -p: vector of probability, -i: class label index, -c: confidence: maximum probability, -n: list of name of class

-
-
-
-
-
-match_feat_fun_na = 'cal_logit_y'
-
-
-
-pred2file(loader_te, device, filename='path_prediction.txt', flag_pred_scalar=False)[source]
-

pred2file dump predicted label to file as sanity check

-
-
-
-training: bool
-
-
-
-
-

domainlab.models.args_jigen module

-

hyper-parameters for JiGen

-
-
-domainlab.models.args_jigen.add_args2parser_jigen(parser)[source]
-

hyper-parameters for JiGen

-
-
-
-

domainlab.models.args_vae module

-
-
-domainlab.models.args_vae.add_args2parser_vae(parser)[source]
-
-
-
-

domainlab.models.model_custom module

-
-
-class domainlab.models.model_custom.AModelCustom(list_str_y, list_str_d=None)[source]
-

Bases: AModelClassif

-

AModelCustom.

-
-
-cal_logit_y(tensor_x)[source]
-

calculate the logit for softmax classification

-
-
-
-abstract property dict_net_module_na2arg_na
-

dict_net_module_na2arg_na. -A dictionary with the key being the pytorch module name and value -being the commandline argument name

-
-
-
-infer_y_vpicn(tensor)[source]
-
-
Parameters:
-

tensor – input

-
-
Returns:
-

    -
  • v - vector of one-hot class label

  • -
  • p - vector of probability

  • -
  • i - class label index

  • -
  • c - confidence: maximum probability

  • -
  • n - list of name of class

  • -
-

-
-
-
-
-
-training: bool
-
-
-
-
-

domainlab.models.model_dann module

-
-
-domainlab.models.model_dann.mk_dann(parent_class=<class 'domainlab.models.a_model_classif.AModelClassif'>)[source]
-

Instantiate a Deep Adversarial Net (DAN) model

-
-
Parameters:
-
    -
  • parent_class (AModel, optional) – Class object determining the task

  • -
  • AModelClassif. (type. Defaults to) –

  • -
-
-
Returns:
-

model inheriting from parent class

-
-
Return type:
-

ModelDAN

-
-
-
-
-
-

domainlab.models.model_deep_all module

-
-
-domainlab.models.model_deep_all.mk_deepall(parent_class=<class 'domainlab.models.a_model_classif.AModelClassif'>)[source]
-

Instantiate a Deepall model

-
-
Parameters:
-

parent_class (AModel, optional) – Class object determining the task type. Defaults to AModelClassif.

-
-
Returns:
-

model inheriting from parent class

-
-
Return type:
-

ModelDeepAlll

-
-
-
-
-
-

domainlab.models.model_diva module

-

DIVA

-
-
-domainlab.models.model_diva.mk_diva(parent_class=<class 'domainlab.models.model_vae_xyd_classif.VAEXYDClassif'>)[source]
-

DIVA with arbitrary task loss

-
-
-
-

domainlab.models.model_hduva module

-

Hierarchical Domain Unsupervised Variational Auto-Encoding

-
-
-domainlab.models.model_hduva.mk_hduva(parent_class=<class 'domainlab.models.model_vae_xyd_classif.VAEXYDClassif'>)[source]
-

Hierarchical Domain Unsupervised VAE with arbitrary task loss

-
-
-
-

domainlab.models.model_jigen module

-

Jigen Model Similar to DANN model

-
-
-domainlab.models.model_jigen.mk_jigen(parent_class=<class 'domainlab.models.a_model_classif.AModelClassif'>)[source]
-

Instantiate a JiGen model

-
-
Parameters:
-
    -
  • parent_class (AModel, optional) – Class object determining the task

  • -
  • AModelClassif. (type. Defaults to) –

  • -
-
-
Returns:
-

model inheriting from parent class

-
-
Return type:
-

ModelJiGen

-
-
-
-
-
-

domainlab.models.model_vae_xyd_classif module

-

Base Class for XYD VAE

-
-
-class domainlab.models.model_vae_xyd_classif.VAEXYDClassif(chain_node_builder, zd_dim, zy_dim, zx_dim, list_str_y, list_str_d)[source]
-

Bases: AModelClassif

-

Base Class for XYD VAE

-
-
-cal_logit_y(tensor_x)[source]
-

calculate the logit for softmax classification

-
-
-
-init_p_zx4batch(batch_size, device)[source]
-
    -
  1. Generate pytorch distribution object.

  2. -
  3. To be called by trainer

  4. -
-
-
Parameters:
-
    -
  • batch_size

  • -
  • device

  • -
-
-
-
-
-
-training: bool
-
-
-
-
-

domainlab.models.wrapper_matchdg module

-

Wrapper for MatchDG to conform of model class in DomainLab

-
-
-class domainlab.models.wrapper_matchdg.ModelWrapMatchDGLogit(net, list_str_y, list_str_d=None)[source]
-

Bases: AModelClassif

-

Wrap an arbitrary model with interface:cal_logit_y

-
-
-cal_logit_y(tensor_x)[source]
-

calculate the logit for softmax classification

-
-
-
-cal_loss(tensor_x, tensor_y, tensor_d=None, others=None)[source]
-

calculate the loss

-
-
-
-cal_reg_loss(tensor_x, tensor_y, tensor_d=None, others=None)[source]
-

task independent regularization loss for domain generalization

-
-
-
-forward(tensor_x)[source]
-

calculate features to be matched

-
-
-
-training: bool
-
-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.tasks.html b/docs/build/html/domainlab.tasks.html deleted file mode 100644 index 36f64fb11..000000000 --- a/docs/build/html/domainlab.tasks.html +++ /dev/null @@ -1,831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.tasks package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.tasks package

-
-

Submodules

-
-
-

domainlab.tasks.a_task_classif module

-

Abstract class for TaskClassif

-
-
-class domainlab.tasks.a_task_classif.NodeTaskDGClassif(succ=None)[source]
-

Bases: AbstractChainNodeHandler

-

Domain Generalization Classification Task

-
-
-property dim_y
-

classification dimension

-
-
-
-abstract get_list_domains()[source]
-
    -
  1. get list of domain names

  2. -
  3. better use method than property so new domains can be added

  4. -
-
-
-
-get_list_domains_tr_te(tr_id, te_id)[source]
-

For static DG task, get train and test domains list.

-
-
Parameters:
-
    -
  • tr_id – training domain ids; -int or str, or a list of int or str, or None; -if None, then assumed to be the complement of te_id.

  • -
  • te_id – test domain ids; -int or str, or a list of int or str; required.

  • -
-
-
Returns:
-

list of training domain names, list of test domain names.

-
-
-
-
-
-get_na(na_tr, na_te)[source]
-

task name appended with configurations -:param na_tr: training domain names -:param na_te: test domain names

-
-
-
-abstract init_business(args)[source]
-

construct loader with resampling -:param seed: random seed for resampling -:param bs: batch size -:param domain_na_tes: test domain names

-
-
-
-is_myjob(request)[source]
-
-
Parameters:
-

request – string

-
-
-
-
-
-abstract property isize
-

image channel, height, width

-
-
-
-property list_domain_tr
-

property getter of list of domains for this task

-
-
-
-abstract property list_str_y
-
-
-
-property loader_te
-

loader of mixed test domains

-
-
-
-property loader_tr
-

loader of mixed train domains

-
-
-
-property loader_val
-

loader of validation dataset on the training domains

-
-
-
-sample_sav(root, batches=5, subfolder_na='task_sample')[source]
-

sample data from task and save to disk

-
-
-
-property task_name
-

The basic name of the task, without configurations

-
-
-
-
-

domainlab.tasks.b_task module

-

Use dictionaries to create train and test domain split

-
-
-class domainlab.tasks.b_task.NodeTaskDict(succ=None)[source]
-

Bases: NodeTaskDGClassif

-

Use dictionaries to create train and test domain split

-
-
-count_domain_class()[source]
-

iterate all domains and count the class label distribution for each -return a double dictionary {“domain1”: {“class1”:3, “class2”: 4,…}, ….}

-
-
-
-decorate_dset(model, args)[source]
-

dispatch re-organization of data flow to model

-
-
-
-get_dset_by_domain(args, na_domain, split=False)[source]
-

each domain correspond to one dataset

-
-
-
-get_list_domains()[source]
-
    -
  1. get list of domain names

  2. -
  3. better use method than property so new domains can be added

  4. -
-
-
-
-init_business(args)[source]
-

create a dictionary of datasets

-
-
-
-property isize
-

image channel, height, width

-
-
-
-property list_str_y
-
-
-
-set_list_domains(list_domains)[source]
-

setter for self._list_domains

-
-
-
-
-

domainlab.tasks.task_folder module

-

When class names and numbers does not match across different domains

-
-
-class domainlab.tasks.task_folder.NodeTaskFolder(succ=None)[source]
-

Bases: NodeTaskDict

-

create dataset by loading files from an organized folder -then each domain correspond to one dataset

-
-
-property dict_domain2imgroot
-

“xx/yy/zz”}

-
-
Type:
-

{“domain name”

-
-
-
-
-
-property extensions
-

return allowed extensions

-
-
-
-get_dset_by_domain(args, na_domain, split=False)[source]
-

each domain correspond to one dataset

-
-
-
-
-class domainlab.tasks.task_folder.NodeTaskFolderClassNaMismatch(succ=None)[source]
-

Bases: NodeTaskFolder

-

when the folder names of the same class from different domains have -different names

-
-
-get_dset_by_domain(args, na_domain, split=False)[source]
-

each domain correspond to one dataset

-
-
-
-
-

domainlab.tasks.task_folder_mk module

-

When class names and numbers does not match across different domains

-
-
-domainlab.tasks.task_folder_mk.mk_task_folder(extensions, list_str_y, dict_domain_folder_name2class, dict_domain_img_trans, img_trans_te, isize, dict_domain2imgroot, taskna, succ=None)[source]
-

Make task by specifying each domain with folder structures -:param extensions: Different Options: 1. a python dictionary with key as the domain name -and value (str or tuple[str]) as the file extensions of the image. 2. a str or tuple[str] -with file extensions for all domains. 3. None: in each domain all files with an extension -in (‘jpg’, ‘jpeg’, ‘png’) are loaded. -:param list_str_y: a python list with user defined class name where -the order of the list matters. -:param dict_domain_folder_name2class: a python dictionary, with key -as the user specified domain name, value as a dictionary to map the -sub-folder name of each domain’s class folder into the user defined -common class name. -:param dict_domain_img_trans: a python dictionary with keys as the user -specified domain name, value as a user defined torchvision transform. -This feature allows carrying out different transformation (composition) to different -domains at training time. -:param img_trans_te: at test or inference time, we do not have knowledge -of domain information so only a unique transform (composition) is allowed. -:isize: domainlab.tasks.ImSize(image channel, image height, image width) -:dict_domain2imgroot: a python dictionary with keys as user specified domain -names and values as the absolute path to each domain’s data. -:taskna: user defined task name

-
-
-
-

domainlab.tasks.task_mnist_color module

-

Color MNIST with palette

-
-
-class domainlab.tasks.task_mnist_color.NodeTaskMNISTColor10(succ=None)[source]
-

Bases: NodeTaskDict

-

Use the deafult palette with 10 colors

-
-
-get_dset_by_domain(args, na_domain, split=True)[source]
-

get_dset_by_domain. -:param args: -:param na_domain: -:param split: for test set, no need to split -args.split: by default, split is set to be zero which in python can -be evaluated in if statement, in which case, no validation set will be -created. Otherwise, this argument is the split ratio

-
-
-
-get_list_domains()[source]
-
    -
  1. get list of domain names

  2. -
  3. better use method than property so new domains can be added

  4. -
-
-
-
-property isize
-

image channel, height, width

-
-
-
-property list_str_y
-
-
-
-
-

domainlab.tasks.task_pathlist module

-

The class TaskPathList provides the user an interface to provide a file with -each line consisting of a pair, where the first slot contains the path -(either absolute or relative if the user knows from where this package is -executed) -of an image and the second slot contains the class label as a numerical string.

-
-
-class domainlab.tasks.task_pathlist.NodeTaskPathListDummy(succ=None)[source]
-

Bases: NodeTaskDict

-
-
-
-domainlab.tasks.task_pathlist.mk_node_task_path_list(isize, list_str_y, trans4all, dict_class_label2name, dict_domain2imgroot, dict_d2filepath_list_img, dict_d2filepath_list_img_val, dict_d2filepath_list_img_te, succ=None)[source]
-

mk_node_task_path_list.

-
-
Parameters:
-
    -
  • isize

  • -
  • list_str_y

  • -
  • trans4all

  • -
  • dict_class_label2name

  • -
  • dict_domain2imgroot

  • -
  • dict_d2filepath_list_img

  • -
  • dict_d2filepath_list_img_val

  • -
  • dict_d2filepath_list_img_te

  • -
  • succ

  • -
-
-
-
-
-
-

domainlab.tasks.task_utils module

-

convert ids to a list of domain names

-
-
-domainlab.tasks.task_utils.parse_domain_id(list_domain_id, list_domains)[source]
-

Convert ids to a list of domain names. -:param list_domain_id: domain id or ids provided as an int or str, -or a list of int or str. -:param list_domains: list of available domains -:return: list of domain names

-
-
-
-

domainlab.tasks.utils_task module

-

Task wraps around datasets, this file provide utilities

-
-
-class domainlab.tasks.utils_task.DsetClassVecDecorator(dset, dict_folder_name2class_global, list_str_y)[source]
-

Bases: Dataset

-

decorate a pytorch dataset with a new class name

-
-
-fun_class_local_na2vec_new(k)[source]
-

local class name within one domain, to one-hot -vector of new representation

-
-
-
-property targets
-

return a list of all targets so class sample count is straight forward

-
-
-
-
-class domainlab.tasks.utils_task.DsetClassVecDecoratorImgPath(dset, dict_folder_name2class_global, list_str_y)[source]
-

Bases: DsetClassVecDecorator

-
-
-
-class domainlab.tasks.utils_task.DsetDomainVecDecorator(dset, vec_domain, na_domain)[source]
-

Bases: Dataset

-

decorate a pytorch dataset with a fixed vector representation of domain

-
-
-property targets
-

return a list of all targets so class sample count is straight forward

-
-
-
-
-class domainlab.tasks.utils_task.DsetDomainVecDecoratorImgPath(dset, vec_domain, na_domain)[source]
-

Bases: DsetDomainVecDecorator

-

Except returning x, y, d, additionally, the path of x is -returned currently not in use since it is mostly important -to print predictions together with path for the test domain

-
-
-
-class domainlab.tasks.utils_task.ImSize(i_c, i_h, i_w)[source]
-

Bases: object

-

ImSize.

-
-
-property c
-

image channel

-
-
-
-property h
-

image height

-
-
-
-property w
-

image width

-
-
-
-
-class domainlab.tasks.utils_task.LoaderDomainLabel(batch_size, dim_d)[source]
-

Bases: object

-

wraps a dataset with domain label and into a loader

-
-
-
-domainlab.tasks.utils_task.img_loader2dir(loader, folder, test=False, list_domain_na=None, list_class_na=None, batches=5)[source]
-

save images from loader to directory so speculate if loader is correct -:param loader: pytorch data loader -:param folder: folder to save images -:param test: if true, the loader is assumend to be a test loader; if false (default) it is assumed to be a train loader -:param list_domain_na: optional list of domain names -:param list_class_na: optional list of class names -:param batches: number of batches to save

-
-
-
-domainlab.tasks.utils_task.mk_loader(dset, bsize, drop_last=True, shuffle=True)[source]
-
-
Parameters:
-

bs – batch size

-
-
-
-
-
-domainlab.tasks.utils_task.mk_onehot(dim, ind)[source]
-
-
Parameters:
-
    -
  • dim – dimension of representation vector

  • -
  • ind – index

  • -
-
-
-
-
-
-domainlab.tasks.utils_task.tensor1hot2ind(tensor_label)[source]
-

tensor1hot2ind.

-
-
Parameters:
-

tensor_label

-
-
-
-
-
-

domainlab.tasks.utils_task_dset module

-
-
-class domainlab.tasks.utils_task_dset.DsetIndDecorator4XYD(dset)[source]
-

Bases: Dataset

-

For dataset of x, y, d, decorate it wih index

-
-
-
-

domainlab.tasks.zoo_tasks module

-
-
-class domainlab.tasks.zoo_tasks.TaskChainNodeGetter(args)[source]
-

Bases: object

-

1. Hardcoded chain -3. Return selected node

-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/domainlab.utils.html b/docs/build/html/domainlab.utils.html deleted file mode 100644 index 8059df8fa..000000000 --- a/docs/build/html/domainlab.utils.html +++ /dev/null @@ -1,788 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab.utils package — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

domainlab.utils package

-
-

Submodules

-
-
-

domainlab.utils.flows_gen_img_model module

-
-
-class domainlab.utils.flows_gen_img_model.FlowGenImgs(model, device)[source]
-

Bases: object

-
-
-gen_img_loader(loader, device, path, domain)[source]
-

gen image for the first batch of input loader

-
-
-
-gen_img_xyd(img, vec_y, vec_d, device, path, folder_na)[source]
-
-
-
-
-domainlab.utils.flows_gen_img_model.fun_gen(model, device, node, args, subfolder_na, output_folder_na='gen')[source]
-
-
-
-

domainlab.utils.generate_benchmark_plots module

-

generate the benchmark plots by calling the gen_bencmark_plots(…) function

-
-
-domainlab.utils.generate_benchmark_plots.gen_benchmark_plots(agg_results: str, output_dir: str)[source]
-

generate the benchmark plots from a csv file containing the aggregated restults. -The csv file must have the columns: -[param_index, task, algo, epos, te_d, seed, params, …] -all columns after seed are intrepreted as objectives of the results, they can e.g. -be acc, precision, recall, specificity, f1, auroc.

-

agg_results: path to the csv file -output_dir: path to a folder which shall contain the results

-
-
-
-domainlab.utils.generate_benchmark_plots.gen_plots(dataframe: DataFrame, output_dir: str)[source]
-

dataframe: dataframe with columns -[’ algo’, ‘ epos’, ‘ te_d’, ‘ seed’, ‘ params’, ‘ acc’, ‘ precision’, … ]

-
-
-
-domainlab.utils.generate_benchmark_plots.max_0_x(x_arg)[source]
-

max(0, x_arg)

-
-
-
-domainlab.utils.generate_benchmark_plots.radar_plot(dataframe_in, file=None, distinguish_hyperparam=True)[source]
-
-
dataframe_in: dataframe containing the data with columns

[algo, epos, te_d, seed, params, obj1, …, obj2]

-
-
-

file: filename to save the plots (if None, the plot will not be saved) -distinguish_param_setups: if True the plot will not only distinguish between models,

-
-

but also between the parameter setups

-
-
-
-
-domainlab.utils.generate_benchmark_plots.round_vals_in_dict(df_column_in)[source]
-

replaces the dictionary by a string containing only the significant digits of the hyperparams -df_column_in: columns of the dataframe containing the dictionary of hyperparams

-
-
-
-domainlab.utils.generate_benchmark_plots.scatterplot(dataframe_in, obj, file=None, kde=True, distinguish_hyperparam=False)[source]
-
-
dataframe: dataframe containing the data with columns

[algo, epos, te_d, seed, params, obj1, …, obj2]

-
-
-

obj1 & obj2: name of the objectives which shall be plotted against each other -file: filename to save the plots (if None, the plot will not be saved) -kde: if True the distribution of the points will be estimated and plotted as kde plot -distinguish_param_setups: if True the plot will not only distinguish between models,

-
-

but also between the parameter setups

-
-
-
-
-domainlab.utils.generate_benchmark_plots.scatterplot_matrix(dataframe_in, file=None, reg=True, distinguish_param_setups=True)[source]
-
-
dataframe: dataframe containing the data with columns

[algo, epos, te_d, seed, params, obj1, …, obj2]

-
-
-

file: filename to save the plots (if None, the plot will not be saved) -reg: if True a regression line will be plotted over the data -distinguish_param_setups: if True the plot will not only distinguish between models,

-
-

but also between the parameter setups

-
-
-
-
-

domainlab.utils.get_git_tag module

-
-
-domainlab.utils.get_git_tag.get_git_tag(print_diff=False)[source]
-
-
-
-

domainlab.utils.hyperparameter_sampling module

-

Samples the hyperparameters according to a benchmark configuration file.

-
-
-class domainlab.utils.hyperparameter_sampling.CategoricalHyperparameter(name: str, config: dict)[source]
-

Bases: Hyperparameter

-

A sampled hyperparameter, which is constraint to fixed, -user given values and datatype

-
-
-datatype()[source]
-

Returns the datatype of this parameter. -This does not apply for references.

-
-
-
-sample()[source]
-

Sample this parameter, respecting properties

-
-
-
-
-class domainlab.utils.hyperparameter_sampling.Hyperparameter(name: str)[source]
-

Bases: object

-

Represents a hyperparameter. -The datatype of .val is int if step and p1 is integer valued, -else float.

-

p1: min or mean -p2: max or scale -reference: None or name of referenced hyperparameter

-
-
-datatype()[source]
-

Returns the datatype of this parameter. -This does not apply for references.

-
-
-
-get_val()[source]
-

Returns the current value of the hyperparameter

-
-
-
-sample()[source]
-

Sample this parameter, respecting properties

-
-
-
-
-class domainlab.utils.hyperparameter_sampling.ReferenceHyperparameter(name: str, config: dict)[source]
-

Bases: Hyperparameter

-

Hyperparameter that references only a different one. -Thus, this parameter is not sampled but set after sampling.

-
-
-datatype()[source]
-

Returns the datatype of this parameter. -This does not apply for references.

-
-
-
-sample()[source]
-

Sample this parameter, respecting properties

-
-
-
-
-class domainlab.utils.hyperparameter_sampling.SampledHyperparameter(name: str, config: dict)[source]
-

Bases: Hyperparameter

-

A numeric hyperparameter that shall be sampled

-
-
-datatype()[source]
-

Returns the datatype of this parameter. -This does not apply for references.

-
-
-
-sample()[source]
-

Sample this parameter, respecting properties

-
-
-
-
-domainlab.utils.hyperparameter_sampling.check_constraints(params: List[Hyperparameter], constraints) bool[source]
-

Check if the constraints are fulfilled.

-
-
-
-domainlab.utils.hyperparameter_sampling.get_hyperparameter(name: str, config: dict) Hyperparameter[source]
-

Factory function. Instantiates the correct Hyperparameter

-
-
-
-domainlab.utils.hyperparameter_sampling.is_task(val) bool[source]
-

Determines if the value of this key is a task.

-
-
-
-domainlab.utils.hyperparameter_sampling.sample_hyperparameters(config: dict, dest: Optional[str] = None) DataFrame[source]
-

Samples the hyperparameters according to the given -config, which should be the dictionary of the full -benchmark config yaml. -Result is saved to ‘output_dir/hyperparameters.csv’ of the -config if not specified explicitly.

-

Note: Parts of the yaml content are executed. Thus use this -only with trusted config files.

-
-
-
-domainlab.utils.hyperparameter_sampling.sample_parameters(params: List[Hyperparameter], constraints) dict[source]
-

Tries to sample from the hyperparameter list.

-

Errors if in 10_0000 attempts no sample complying with the -constraints is found.

-
-
-
-domainlab.utils.hyperparameter_sampling.sample_task(num_samples: int, sample_df: DataFrame, task_name: str, config: dict)[source]
-

Sample one task and add it to the dataframe

-
-
-
-

domainlab.utils.override_interface module

-
-
-domainlab.utils.override_interface.override_interface(interface_class)[source]
-

overrides. -:param interface_class: the interface class name, always specify this -explicitly as otherwise interface_class is going to be the nearest -function it decorate, and argument “method2override” of returned -function “overrider” accept will be the current child class

-
class BaseClass()
-class Child(BaseClass):
-    @overrides(BaseClass)
-    def fun(self):
-        pass
-
-
-
-
-
-

domainlab.utils.perf module

-

Classification Performance

-
-
-class domainlab.utils.perf.PerfClassif[source]
-

Bases: object

-

Classification Performance

-
-
-classmethod cal_acc(model, loader_te, device, max_batches=None)[source]
-
-
Parameters:
-
    -
  • model

  • -
  • loader_te

  • -
  • device – for final test, GPU can be used

  • -
  • max_batches – maximum number of iteration for data loader, used to -probe performance with less computation burden. -default None, which means to traverse the whole dataset

  • -
-
-
-
-
-
-classmethod gen_fun_acc(dim_target)[source]
-
-
Parameters:
-

dim_target – class/domain label embeding dimension

-
-
-
-
-
-
-

domainlab.utils.perf_metrics module

-

Classification Performance

-
-
-class domainlab.utils.perf_metrics.PerfMetricClassif(num_classes, average='macro')[source]
-

Bases: object

-

Classification Performance metrics

-
-
-cal_metrics(model, loader_te, device, max_batches=None)[source]
-
-
Parameters:
-
    -
  • model

  • -
  • loader_te

  • -
  • device – for final test, GPU can be used

  • -
  • max_batches – maximum number of iteration for data loader, used to -probe performance with less computation burden. -default None, which means to traverse the whole dataset

  • -
-
-
-
-
-
-
-

domainlab.utils.test_img module

-
-
-domainlab.utils.test_img.mk_img(i_h, i_ch=3, batch_size=5)[source]
-
-
-
-domainlab.utils.test_img.mk_rand_label_onehot(target_dim=10, batch_size=5)[source]
-
-
-
-domainlab.utils.test_img.mk_rand_xyd(ims, y_dim, d_dim, batch_size)[source]
-
-
-
-

domainlab.utils.u_import module

-
-
-domainlab.utils.u_import.import_path(path)[source]
-
-
-
-

domainlab.utils.u_import_net_module module

-

import external neural network implementation

-
-
-domainlab.utils.u_import_net_module.build_external_obj_net_module_feat_extract(mpath, dim_y, remove_last_layer)[source]
-

The user provide a function to initiate an object of the neural network, -which is fine for training but problematic for persistence of the trained -model since it is created externally. -:param mpath: path of external python file where the neural network -architecture is defined -:param dim_y: dimension of features

-
-
-
-

domainlab.utils.utils_class module

-
-
-domainlab.utils.utils_class.store_args(method)[source]
-

Stores provided method args as instance attributes.

-
-
-
-

domainlab.utils.utils_classif module

-
-
-domainlab.utils.utils_classif.get_label_na(tensor_ind, list_str_na)[source]
-

given list of label names in strings, map tensor of index to label names

-
-
-
-domainlab.utils.utils_classif.logit2preds_vpic(logit)[source]
-
-
Logit:
-

batch of logit vector

-
-
Returns:
-

vector of one-hot, -vector of probability, -index, -maximum probability

-
-
-
-
-
-domainlab.utils.utils_classif.mk_dummy_label_list_str(prefix, dim)[source]
-

only used for testing, to generate list of class/domain label names

-
-
-
-

domainlab.utils.utils_cuda module

-
-
-domainlab.utils.utils_cuda.get_device(flag_no_cu)[source]
-
-
-
-

domainlab.utils.utils_img_sav module

-
-
-domainlab.utils.utils_img_sav.mk_fun_sav_img(path='.', nrow=8, folder_na='')[source]
-

create torchvision.utils image saver

-
-
-
-domainlab.utils.utils_img_sav.sav_add_title(grid_img, path, title)[source]
-

add title and save image as matplotlib.pyplot

-
-
-
-

Module contents

-
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/figs/tikz_hduva.pdf b/docs/build/html/figs/tikz_hduva.pdf deleted file mode 100644 index 9ca31ab1d..000000000 Binary files a/docs/build/html/figs/tikz_hduva.pdf and /dev/null differ diff --git a/docs/build/html/figs/tikz_hduva.svg b/docs/build/html/figs/tikz_hduva.svg deleted file mode 100644 index 159e7eb91..000000000 --- a/docs/build/html/figs/tikz_hduva.svg +++ /dev/null @@ -1,534 +0,0 @@ - -image/svg+xmlα -s -z -d -y -z -y -X -z -x -N -0 -, -1 -q -ω -( -y -| -z -y -) - \ No newline at end of file diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html deleted file mode 100644 index e3c16816e..000000000 --- a/docs/build/html/genindex.html +++ /dev/null @@ -1,2123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- - -

Index

- -
- A - | B - | C - | D - | E - | F - | G - | H - | I - | L - | M - | N - | O - | P - | R - | S - | T - | U - | V - | W - -
-

A

- - - -
- -

B

- - - -
- -

C

- - - -
- -

D

- - - -
- -

E

- - - -
- -

F

- - - -
- -

G

- - - -
- -

H

- - - -
- -

I

- - - -
- -

L

- - - -
- -

M

- - - -
- -

N

- - - -
- -

O

- - - -
- -

P

- - - -
- -

R

- - - -
- -

S

- - - -
- -

T

- - - -
- -

U

- - -
- -

V

- - -
- -

W

- - - -
- - - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/index.html b/docs/build/html/index.html deleted file mode 100644 index b9d4a35ab..000000000 --- a/docs/build/html/index.html +++ /dev/null @@ -1,381 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Welcome to domainlab’s documentation! — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - - - - - - - \ No newline at end of file diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html deleted file mode 100644 index 6b8f9d2d4..000000000 --- a/docs/build/html/modules.html +++ /dev/null @@ -1,467 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - domainlab — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- -
-
- -
-
-
-
-
- - -
-
-
- -
-
- -
-

domainlab

-
- -
-
- - -
-
-
-
-
- - - - - \ No newline at end of file diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv deleted file mode 100644 index 9d61d9852..000000000 Binary files a/docs/build/html/objects.inv and /dev/null differ diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html deleted file mode 100644 index 5fcfa9bb7..000000000 --- a/docs/build/html/py-modindex.html +++ /dev/null @@ -1,826 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Python Module Index — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- - -

Python Module Index

- -
- d -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
- d
- domainlab -
    - domainlab.algos -
    - domainlab.algos.a_algo_builder -
    - domainlab.algos.builder_custom -
    - domainlab.algos.builder_dann -
    - domainlab.algos.builder_deepall -
    - domainlab.algos.builder_dial -
    - domainlab.algos.builder_diva -
    - domainlab.algos.builder_hduva -
    - domainlab.algos.builder_jigen1 -
    - domainlab.algos.builder_matchdg -
    - domainlab.algos.compos -
    - domainlab.algos.compos.matchdg_args -
    - domainlab.algos.compos.matchdg_base -
    - domainlab.algos.compos.matchdg_ctr_erm -
    - domainlab.algos.compos.matchdg_match -
    - domainlab.algos.compos.matchdg_utils -
    - domainlab.algos.msels -
    - domainlab.algos.msels.a_model_sel -
    - domainlab.algos.msels.c_msel -
    - domainlab.algos.msels.c_msel_oracle -
    - domainlab.algos.observers -
    - domainlab.algos.observers.a_observer -
    - domainlab.algos.observers.b_obvisitor -
    - domainlab.algos.observers.c_obvisitor_cleanup -
    - domainlab.algos.observers.c_obvisitor_gen -
    - domainlab.algos.trainers -
    - domainlab.algos.trainers.a_trainer -
    - domainlab.algos.trainers.args_dial -
    - domainlab.algos.trainers.train_basic -
    - domainlab.algos.trainers.train_dial -
    - domainlab.algos.trainers.train_matchdg -
    - domainlab.algos.trainers.train_visitor -
    - domainlab.algos.zoo_algos -
    - domainlab.arg_parser -
    - domainlab.compos -
    - domainlab.compos.a_nn_builder -
    - domainlab.compos.builder_nn_alex -
    - domainlab.compos.builder_nn_conv_bn_relu_2 -
    - domainlab.compos.builder_nn_external_from_file -
    - domainlab.compos.nn_zoo -
    - domainlab.compos.nn_zoo.net_adversarial -
    - domainlab.compos.nn_zoo.net_classif -
    - domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 -
    - domainlab.compos.nn_zoo.net_gated -
    - domainlab.compos.nn_zoo.nn -
    - domainlab.compos.nn_zoo.nn_alex -
    - domainlab.compos.nn_zoo.nn_torchvision -
    - domainlab.compos.utils_conv_get_flat_dim -
    - domainlab.compos.zoo_nn -
    - domainlab.dsets -
    - domainlab.dsets.a_dset_mnist_color_rgb_solo -
    - domainlab.dsets.dset_img_path_list -
    - domainlab.dsets.dset_mnist_color_solo_default -
    - domainlab.dsets.dset_poly_domains_mnist_color_default -
    - domainlab.dsets.dset_subfolder -
    - domainlab.dsets.utils_color_palette -
    - domainlab.dsets.utils_data -
    - domainlab.dsets.utils_wrapdset_patches -
    - domainlab.exp_protocol -
    - domainlab.exp_protocol.run_experiment -
    - domainlab.models -
    - domainlab.models.a_model -
    - domainlab.models.a_model_classif -
    - domainlab.models.args_jigen -
    - domainlab.models.args_vae -
    - domainlab.models.model_custom -
    - domainlab.models.model_dann -
    - domainlab.models.model_deep_all -
    - domainlab.models.model_diva -
    - domainlab.models.model_hduva -
    - domainlab.models.model_jigen -
    - domainlab.models.model_vae_xyd_classif -
    - domainlab.models.wrapper_matchdg -
    - domainlab.tasks -
    - domainlab.tasks.a_task_classif -
    - domainlab.tasks.b_task -
    - domainlab.tasks.task_folder -
    - domainlab.tasks.task_folder_mk -
    - domainlab.tasks.task_mnist_color -
    - domainlab.tasks.task_pathlist -
    - domainlab.tasks.task_utils -
    - domainlab.tasks.utils_task -
    - domainlab.tasks.utils_task_dset -
    - domainlab.tasks.zoo_tasks -
    - domainlab.utils -
    - domainlab.utils.flows_gen_img_model -
    - domainlab.utils.generate_benchmark_plots -
    - domainlab.utils.get_git_tag -
    - domainlab.utils.hyperparameter_sampling -
    - domainlab.utils.override_interface -
    - domainlab.utils.perf -
    - domainlab.utils.perf_metrics -
    - domainlab.utils.test_img -
    - domainlab.utils.u_import -
    - domainlab.utils.u_import_net_module -
    - domainlab.utils.utils_class -
    - domainlab.utils.utils_classif -
    - domainlab.utils.utils_cuda -
    - domainlab.utils.utils_img_sav -
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/readme_link.html b/docs/build/html/readme_link.html deleted file mode 100644 index a04dd3b10..000000000 --- a/docs/build/html/readme_link.html +++ /dev/null @@ -1,424 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introduction — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - - - -
-
- -
-

Introduction

-
-

DomainLab: Playground for Domain Generalization

-

GH Actions CI -codecov -Codacy Badge

-
-

Domain Generalization and DomainLab

-

Domain Generalization aims at learning domain invariant features by utilizing data from multiple domains so the learned feature can generalize to new unseen domains.

-
-
-

Why a dedicated package

-

Domain generalization algorithm try to learn domain invariant features by adding regularization upon the ERM (Emperical Risk Minimization) loss. A typical setting of evaluating domain generalization algorithm is the so called leave-one-domain-out scheme, where one dataset is collected from each distribution. Each time, one dataset/domain is left as test-set to estimate the generalization performance of a model trained upon the rest of domains/datasets.

-

Once you came across a claim, that a domain generalization algorithm A can generate a “better” model h upon some datasets D with “better” performance compared to other algorithms, have you ever wondered:

-
    -
  • Is this mostly attributed to a more “powerful” neural network architecture of model A compared to others? What will happen if I change the backbone neural network of algorithm A from ResNet to AlexNet?

  • -
  • Is this mostly attributed the protocol of estimating the generalization performance? e.g. dataset split, Will this algorithm “work” for my datasets?

  • -
  • Is this mostly attributed to the “clever” regularization algorithm or a special loss function A has used for the neural network?

  • -
-

To maximally decouple these attributing factors, DomainLab was implemented with software design patterns, where

-
    -
  • Domain generalization algorithms was implemented in a way that keeps the underlying neural network architecture transparent, i.e. the concrete neural network architecture can be replaced like a plugin through specifying a custom neural network architecture implemented in a python file. See Specify Custom Neural Networks for an algorithm

  • -
  • To evaluate a domain generalization algorithm’s performance, the user can specify a “Task” in the form of custom python file and feed into the command line argument, thus it is at the user’s discretion on how to evaluate an algorithm, so that all domain generalization algorithms could be compared fairly. See Task Specification.

  • -
  • To simply test an algorithm’s performance, there is no need to change any code inside this repository, the user only need to extend this repository to fit their custom need.

  • -
-
-
-

Getting started

-
-

Installation

-
    -
  • Install via python-poetry: -Read the python-poetry documentation https://python-poetry.org/ and use the configuration file in this repository.

  • -
  • Or only install dependencies via pip -Suppose you have cloned the repository and have changed directory to the cloned repository.

  • -
-
pip install -r requirements.txt
-
-
-
-
-

Basic usage

-

Suppose you have cloned the repository and the dependencies ready, change directory to the repository: -DomainLab comes with some minimal toy-dataset to test its basis functionality. To train a domain generalization model with a user-specified task, one can execute a command similar to the following.

-
python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --aname=diva --gamma_y=7e5 --gamma_d=1e5 --nname=alexnet --nname_dom=conv_bn_pool_2
-
-
-

where --tpath specifies the path of a user specified python file which defines the domain generalization task, see Example in Task Specification. --aname specifies which algorithm to use, see Available Algorithms, --bs specifies the batch size, --debug restrain only running for 2 epochs and save results with prefix ‘debug’. For DIVA, the hyper-parameters include --gamma_y=7e5 which is the relative weight of ERM loss compared to ELBO loss, and --gamma_d=1e5, which is the relative weight of domain classification loss compared to ELBO loss. ---nname is to specify which neural network to use for feature extraction for classification, --nname_dom is to specify which neural network to use for feature extraction of domains. -For usage of other arguments, check with

-
python main_out.py --help
-
-
-

See also Examples.

-
-
-

Output structure (results storage) and Performance Measure

-

Output structure and Performance Measure

-
-
-
-

Custom Usage

-
-

Define your task

-

Do you have your own data that comes from different domains? Create a task for your data and benchmark different domain generlization algorithms according to the following example. See -Task Specification

-
-
-

Custom Neural network

-

This library decouples the concept of algorithm (model) and neural network architecture where the user could plugin different neural network architectures for the same algorithm. See -Specify Custom Neural Networks for an algorithm

-
-
-
-

Software Design Pattern, Extend or Contribution, Credits

-

Extend or Contibute

-
-
-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/requirements.html b/docs/build/html/requirements.html deleted file mode 100644 index ca6d67e3c..000000000 --- a/docs/build/html/requirements.html +++ /dev/null @@ -1,323 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - recommonmark==0.5.0.dev0 — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

linkify-it-py -m2r2 -myst-parser -rinohtype -nbsphinx -nbsphinx_link -sphinx_material -commonmark

-
-

recommonmark==0.5.0.dev0

-

git+https://github.com/rtfd/recommonmark

-
- - -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/search.html b/docs/build/html/search.html deleted file mode 100644 index 8686909f6..000000000 --- a/docs/build/html/search.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Search — domainlab documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content -
- -
- - -
- - - - -
-
- - -
-
-
- - -
-
-
- -
-
- -

Search

-
- -

- Please activate JavaScript to enable the search - functionality. -

-
- -
- -
- -
-
-
-
-
-
- - -
- - - - \ No newline at end of file diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js deleted file mode 100644 index 2d58a4b32..000000000 --- a/docs/build/html/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({"docnames": ["docHDUVA", "docJiGen", "doc_algos", "doc_benchmark", "doc_custom_nn", "doc_diva", "doc_examples", "doc_extend_contribute", "doc_output", "doc_tasks", "domainlab", "domainlab.algos", "domainlab.algos.compos", "domainlab.algos.msels", "domainlab.algos.observers", "domainlab.algos.trainers", "domainlab.compos", "domainlab.compos.nn_zoo", "domainlab.dsets", "domainlab.exp_protocol", "domainlab.models", "domainlab.tasks", "domainlab.utils", "index", "modules", "readme_link", "requirements"], "filenames": ["docHDUVA.md", "docJiGen.md", "doc_algos.md", "doc_benchmark.md", "doc_custom_nn.md", "doc_diva.md", "doc_examples.md", "doc_extend_contribute.md", "doc_output.md", "doc_tasks.md", "domainlab.rst", "domainlab.algos.rst", "domainlab.algos.compos.rst", "domainlab.algos.msels.rst", "domainlab.algos.observers.rst", "domainlab.algos.trainers.rst", "domainlab.compos.rst", "domainlab.compos.nn_zoo.rst", "domainlab.dsets.rst", "domainlab.exp_protocol.rst", "domainlab.models.rst", "domainlab.tasks.rst", "domainlab.utils.rst", "index.rst", "modules.rst", "readme_link.rst", "requirements.txt"], "titles": ["HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION", "JiGen", "Overview of implemented models and algorithms", "Benchmarking with DomainLab", "Custom Neural Network", "DIVA: Domain Invariant Variational Autoencoders", "Examples", "Extend or contribute with a custom domain generalization algorithm", "Output structure", "Task Specification", "domainlab package", "domainlab.algos package", "domainlab.algos.compos package", "domainlab.algos.msels package", "domainlab.algos.observers package", "domainlab.algos.trainers package", "domainlab.compos package", "domainlab.compos.nn_zoo package", "domainlab.dsets package", "domainlab.exp_protocol package", "domainlab.models package", "domainlab.tasks package", "domainlab.utils package", "Welcome to domainlab\u2019s documentation!", "domainlab", "Introduction", "recommonmark==0.5.0.dev0"], "terms": {"build": [0, 11], "approach": [0, 5], "within": [0, 3, 17, 20, 21], "framework": 0, "autoencod": [0, 2, 23], "facilit": 0, "new": [0, 5, 21, 25], "without": [0, 17, 21], "supervis": [0, 5], "learn": [0, 2, 5, 11, 12, 15, 25], "represent": [0, 21], "disentangl": [0, 5], "specif": [0, 3, 5, 22, 25], "inform": [0, 5, 9, 21], "from": [0, 1, 2, 3, 4, 5, 8, 9, 10, 12, 13, 15, 17, 19, 20, 21, 22, 25], "class": [0, 5, 9, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22], "label": [0, 1, 5, 9, 20, 21, 22], "even": [0, 16], "complex": 0, "set": [0, 1, 5, 12, 15, 19, 21, 22, 25], "where": [0, 3, 4, 5, 7, 9, 12, 21, 22, 25], "structur": [0, 9, 18, 21], "observ": [0, 2, 10, 11, 13, 15], "dure": [0, 5, 15, 17], "train": [0, 1, 2, 3, 5, 8, 9, 11, 12, 13, 14, 15, 17, 18, 20, 21, 22, 25], "more": [0, 16, 25], "base": [0, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22], "three": [0, 5], "latent": [0, 5], "variabl": [0, 5], "ar": [0, 1, 3, 5, 8, 9, 17, 19, 20, 21, 22], "us": [0, 1, 2, 3, 4, 5, 13, 15, 17, 18, 19, 20, 21, 22, 25], "distinct": 0, "sourc": [0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "denot": 0, "z_y": 0, "z_d": 0, "z_x": 0, "repres": [0, 17, 22], "residu": [0, 5], "varianc": [0, 5], "input": [0, 17, 20, 22], "we": [0, 3, 9, 12, 19, 21], "introduc": 0, "an": [0, 2, 3, 5, 8, 9, 17, 18, 20, 21, 22, 25], "addit": [0, 5, 19], "level": 0, "continu": 0, "s": [0, 9, 18, 21, 25], "potenti": [0, 8], "unobserv": 0, "thi": [0, 1, 3, 4, 5, 7, 8, 9, 15, 17, 19, 21, 22, 25], "mean": [0, 8, 17, 22], "can": [0, 1, 2, 3, 4, 5, 7, 8, 9, 11, 16, 17, 20, 21, 22, 25], "encourag": [0, 5], "through": [0, 25], "condit": [0, 5], "prior": 0, "need": [0, 5, 9, 11, 17, 21, 25], "one": [0, 1, 3, 5, 9, 12, 17, 18, 19, 20, 21, 22, 25], "hot": [0, 20, 21, 22], "The": [0, 1, 2, 3, 5, 8, 9, 17, 21, 22], "along": 0, "its": [0, 25], "shown": [0, 9], "figur": 0, "1": [0, 2, 3, 6, 9, 11, 16, 17, 18, 21], "probabilist": 0, "graphic": [0, 3], "note": [0, 2, 3, 7, 17, 22], "part": [0, 12, 22], "x": [0, 17, 20, 21], "concatent": 0, "dash": 0, "arrow": 0, "requir": [0, 1, 17, 21, 25], "respec": 0, "network": [0, 1, 2, 5, 7, 11, 16, 22], "elbo": [0, 25], "decompos": [0, 2], "4": [0, 6, 17, 18, 21], "differ": [0, 3, 5, 7, 8, 9, 11, 16, 21, 22, 25], "term": 0, "likelihood": 0, "e_": 0, "q": 0, "log": 0, "p_": 0, "theta": 0, "kl": 0, "diverg": 0, "weight": [0, 1, 11, 15, 16, 25], "beta": 0, "vae": [0, 17, 20], "beta_x": 0, "q_": 0, "phi_x": 0, "theta_x": 0, "beta_i": 0, "phi_i": 0, "theta_i": 0, "y": [0, 5, 20, 21], "beta_d": 0, "phi_": 0, "phi_d": 0, "frac": 0, "theta_d": 0, "topic": [0, 17], "beta_t": 0, "theta_": 0, "alpha": [0, 15, 17], "In": [0, 3, 5, 9, 16, 17], "construct": [0, 11, 16, 21], "ad": [0, 7, 15, 16, 21, 25], "auxiliari": 0, "classsifi": 0, "gamma_i": [0, 5, 6, 25], "For": [0, 1, 3, 9, 14, 17, 21, 25], "fit": [0, 25], "specifi": [0, 2, 3, 5, 7, 8, 16, 21, 22, 25], "relat": [0, 3], "well": [0, 3, 15], "follow": [0, 4, 5, 9, 17, 25], "size": [0, 3, 5, 21, 25], "space": [0, 5], "zd_dim": [0, 5, 20], "zx_dim": [0, 5, 20], "zy_dim": [0, 5, 20], "topic_dim": 0, "imag": [0, 1, 2, 5, 8, 9, 11, 15, 16, 17, 18, 20, 21, 22], "topic_h_dim": 0, "img_h_dim": 0, "final": [0, 13, 22], "2": [0, 3, 5, 17, 18, 21, 25], "A": [0, 20, 22, 25], "convert": [0, 7, 21], "distribut": [0, 3, 20, 21, 22, 25], "concaten": 0, "name": [0, 2, 3, 7, 9, 11, 16, 18, 20, 21, 22], "path": [0, 9, 16, 17, 18, 19, 21, 22, 25], "nname_topic_distrib_img2top": [0, 6], "npath_topic_distrib_img2top": [0, 6], "nname_encoder_sandwich_layer_img2h4zd": [0, 6], "npath_encoder_sandwich_layer_img2h4zd": [0, 6], "number": [0, 3, 15, 17, 19, 21, 22], "epoch": [0, 3, 12, 14, 15, 25], "hyper": [0, 1, 15, 19, 20, 25], "warm": 0, "up": [0, 15], "via": [0, 4, 7, 9, 25], "argument": [0, 3, 8, 9, 10, 16, 17, 19, 20, 21, 22, 25], "pleas": 0, "cite": 0, "our": 0, "paper": [0, 5], "you": [0, 17, 25], "find": [0, 15], "inproceed": 0, "sun2021hierarch": 0, "titl": [0, 22], "author": 0, "sun": 0, "xudong": 0, "buettner": 0, "florian": 0, "booktitl": 0, "iclr": [0, 2], "2021": [0, 2], "robustml": [0, 2], "workshop": 0, "http": [0, 1, 2, 4, 5, 17, 18, 25, 26], "arxiv": [0, 1, 2, 5], "org": [0, 1, 2, 5, 17, 18, 25], "pdf": [0, 2, 5], "2101": [0, 2], "09436": [0, 2], "year": 0, "method": [1, 20, 21, 22], "propos": 1, "ab": [1, 2], "2007": 1, "01434": 1, "carlucci": [1, 2], "et": [1, 2], "al": [1, 2], "extend": [1, 17, 19], "understand": 1, "concept": [1, 2, 25], "spatial": 1, "correl": 1, "neuron": 1, "onli": [1, 2, 3, 5, 8, 9, 15, 18, 21, 22, 25], "classif": [1, 5, 9, 20, 21, 22, 25], "task": [1, 3, 4, 7, 8, 10, 12, 15, 18, 19, 20, 22, 24], "also": [1, 3, 5, 9, 17, 22, 25], "solv": [1, 2], "jigsaw": [1, 2], "puzzl": [1, 2], "split": [1, 8, 21, 25], "n": [1, 20], "time": [1, 9, 19, 21, 25], "patch": 1, "permut": [1, 18], "model": [1, 5, 8, 10, 11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25], "predict": [1, 5, 8, 20, 21], "index": [1, 18, 19, 20, 21, 22, 23], "which": [1, 3, 7, 8, 9, 17, 21, 22, 25], "result": [1, 8, 19, 22], "To": [1, 3, 4, 9, 20, 25], "abl": 1, "problem": [1, 5], "parallel": [1, 3], "shuffl": [1, 11, 18, 21], "order": [1, 5, 9, 21], "first": [1, 3, 17, 21, 22], "fed": [1, 5], "convolut": [1, 16, 17], "featur": [1, 5, 9, 16, 17, 20, 21, 22, 25], "extract": [1, 3, 16, 17, 25], "given": [1, 3, 17, 18, 22], "classifi": [1, 5, 9, 17], "classificaiton": 1, "cross": [1, 20], "entropi": [1, 20], "loss": [1, 2, 13, 20, 23, 25], "both": [1, 18], "while": [1, 2, 17], "paramet": [1, 3, 5, 11, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25], "addition": [1, 5, 21], "rel": [1, 8, 21, 25], "ratio": [1, 21], "probabl": [1, 20, 22], "tile": [1, 11, 18], "instanc": [1, 8, 17, 22], "data": [1, 5, 11, 12, 15, 17, 19, 21, 22, 25], "anoth": [1, 9, 17], "advantag": [1, 5], "doe": [1, 5, 9, 12, 13, 21, 22], "domain": [1, 2, 3, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23], "despit": 1, "miss": [1, 5], "domainlab": [2, 4, 7], "That": 2, "defin": [2, 7, 9, 17, 21, 22], "neural": [2, 7, 11, 16, 22], "architectur": [2, 22, 25], "independ": [2, 5, 20], "compon": [2, 11, 17], "share": [2, 12], "same": [2, 3, 8, 9, 12, 16, 17, 21, 25], "default": [2, 8, 20, 21, 22], "pool": 2, "all": [2, 3, 5, 7, 9, 17, 18, 20, 21, 22, 25], "togeth": [2, 21], "erm": [2, 25], "empir": 2, "risk": [2, 25], "minim": [2, 25], "mahajan": 2, "divyat": 2, "shruti": 2, "topl": 2, "amit": 2, "sharma": 2, "gener": [2, 5, 8, 9, 14, 15, 18, 20, 21, 22, 23], "causal": 2, "match": [2, 12, 20, 21], "intern": 2, "confer": 2, "machin": 2, "pmlr": [2, 5], "ils": 2, "maximilian": 2, "invari": [2, 11, 15, 23, 25], "variat": [2, 3, 19, 20, 23], "medic": [2, 5], "deep": [2, 5, 20], "2020": [2, 5], "hierarch": [2, 20, 23], "auto": [2, 9, 20, 23], "encod": [2, 5, 17, 20, 23], "unsupervis": [2, 5, 20, 23], "ganin": 2, "yaroslav": 2, "adversari": [2, 11, 15, 20], "journal": 2, "research": 2, "17": 2, "2016": 2, "2096": 2, "2030": 2, "fabio": 2, "m": 2, "proceed": 2, "ieee": 2, "cvf": 2, "comput": [2, 17, 22], "vision": [2, 18], "pattern": [2, 11, 13, 14, 16], "recognit": 2, "2019": 2, "1903": 2, "06864": 2, "levi": 2, "matan": 2, "idan": 2, "attia": 2, "aryeh": 2, "kontorovich": 2, "transact": 2, "preprint": 2, "2104": 2, "00322": 2, "packag": [3, 8, 9, 23, 24], "offer": [3, 9], "abil": 3, "algorithm": [3, 8, 11, 15, 16, 18, 19, 23, 25], "against": [3, 22], "each": [3, 8, 9, 12, 15, 16, 17, 18, 19, 21, 22, 25], "other": [3, 12, 17, 18, 20, 22, 25], "collect": [3, 25], "csv": [3, 8, 19, 22], "file": [3, 4, 7, 8, 9, 16, 18, 19, 20, 21, 22, 25], "prepar": [3, 5], "chart": 3, "two": [3, 5, 12], "aspect": 3, "consid": [3, 15, 18], "stochast": [3, 19], "perform": [3, 5, 15, 17, 20, 22], "respect": [3, 5, 9, 22], "random": [3, 15, 19, 21], "seed": [3, 19, 21, 22], "sensit": 3, "select": [3, 11, 13, 14, 16, 21], "By": [3, 5, 8], "randomli": [3, 15], "choic": 3, "investig": 3, "yaml": [3, 19, 22], "refer": [3, 5, 22], "demo_benchmark": 3, "document": [3, 25], "exampl": [3, 7, 9, 25], "As": 3, "see": [3, 4, 9, 25], "here": [3, 20], "user": [3, 4, 8, 9, 16, 18, 21, 22, 25], "ha": [3, 4, 12, 17, 18, 25], "common": [3, 9, 21], "typic": [3, 25], "includ": [3, 18, 25], "dataset": [3, 12, 18, 21, 22, 25], "shall": [3, 5, 9, 22], "batch": [3, 12, 15, 17, 21, 22, 25], "leav": [3, 19, 25], "out": [3, 5, 9, 13, 17, 19, 21, 25], "test": [3, 5, 8, 9, 13, 19, 21, 22, 25], "contain": [3, 5, 7, 8, 9, 18, 21, 22], "fix": [3, 21, 22], "vari": 3, "sampling_se": 3, "fulli": [3, 5, 16, 17], "reproduc": 3, "possibl": [3, 5, 16], "demo_hypeparameter_sampl": 3, "yml": 3, "cours": 3, "directli": [3, 17], "singl": [3, 5, 18, 19], "everi": [3, 17], "node": [3, 11, 16, 21, 22], "anam": [3, 4, 6, 7, 25], "constraint": [3, 15, 22], "between": [3, 8, 9, 22], "categor": 3, "type": [3, 17, 20, 21], "list": [3, 9, 18, 20, 21, 22], "valid": [3, 18, 21], "valu": [3, 9, 15, 17, 20, 21, 22], "equal": 3, "support": [3, 5], "section": 3, "enforc": [3, 17], "kei": [3, 9, 12, 19, 20, 21, 22], "p4": 3, "task1": 3, "referenc": [3, 22], "undefin": 3, "behaviour": 3, "alwai": [3, 5, 16, 22], "drawn": 3, "ignor": [3, 17, 18, 19], "reject": 3, "If": [3, 17], "10": [3, 17, 21, 22], "000": 3, "row": [3, 18, 19], "abort": 3, "error": [3, 22], "execut": [3, 21, 22, 25], "command": [3, 8, 9, 10, 16, 25], "found": [3, 4, 9, 22], "sever": [3, 7, 8, 18, 19], "core": 3, "provid": [3, 9, 18, 21, 22], "per": [3, 15], "creat": [3, 9, 12, 21, 22, 25], "save": [3, 13, 17, 21, 22, 25], "output": [3, 16, 17, 19], "directori": [3, 8, 9, 18, 21, 25], "moreov": 3, "subdirectori": 3, "visual": 3, "interpret": 3, "implement": [4, 9, 22, 23, 25], "signatur": [4, 9], "python": [4, 7, 9, 16, 21, 22, 25], "feed": [4, 11, 25], "librari": [4, 25], "npath": [4, 6, 16], "def": [4, 9, 22], "build_feat_extract_net": 4, "dim_i": [4, 12, 17, 20, 21, 22], "remove_last_lay": [4, 16, 22], "below": [4, 5, 8, 9], "net": [4, 7, 20], "resnet": [4, 6, 7, 25], "py": [4, 6, 7, 18, 25, 26], "folder": [4, 8, 9, 18, 21, 22], "code": [4, 9, 16, 25], "repositori": [4, 9, 25], "github": [4, 18, 26], "com": [4, 18, 26], "marrlab": 4, "blob": [4, 18], "master": 4, "main_out": [4, 6, 7, 25], "te_d": [4, 6, 7, 22, 25], "caltech": [4, 6, 7, 25], "mini_vlc": [4, 6, 7], "debug": [4, 6, 7, 25], "bs": [4, 6, 7, 21, 25], "8": [4, 17, 18, 22], "epochs_ctr": [4, 6], "3": [4, 6, 7, 9, 11, 16, 17, 18, 21, 22], "epochs_erm": [4, 6], "store": [5, 9, 17, 22], "obtain": 5, "margin": 5, "densiti": 5, "These": 5, "parameter": 5, "learnabl": 5, "decod": 5, "reconstruct": 5, "emphas": 5, "captur": 5, "lead": 5, "overal": [5, 23], "larg": 5, "howev": 5, "infer": [5, 9, 17, 21], "experi": [5, 11, 19], "show": [5, 17], "inde": 5, "semi": 5, "some": [5, 9, 16, 25], "accuraci": 5, "further": 5, "improv": 5, "sens": 5, "turn": 5, "notabl": 5, "better": [5, 21, 25], "close": 5, "therefor": 5, "setup": [5, 22], "allow": [5, 9, 18, 21], "sampl": [5, 19, 21, 22], "end": [5, 18], "sinc": [5, 17, 21, 22], "clear": 5, "what": [5, 19, 25], "actual": 5, "exist": [5, 8, 9, 16], "decreas": 5, "multipli": 5, "alpha_i": 5, "eq": 5, "d": [5, 20, 21, 25], "alpha_d": 5, "gamma_d": [5, 6, 25], "1905": 5, "10427": 5, "0": [6, 9, 12, 17, 22], "mnistcolor10": 6, "keep_model": [6, 8], "nname": [6, 16, 25], "conv_bn_pool_2": [6, 25], "nname_dom": [6, 25], "10e5": 6, "1e5": [6, 25], "tr_d": 6, "7": [6, 9, 17], "7e5": [6, 25], "alexnet": [6, 7, 17, 25], "npath_dom": 6, "san_check": 6, "san_num": 6, "gen": [6, 8, 22], "pperm": 6, "nperm": 6, "100": [6, 18], "grid_len": [6, 18], "tpath": [6, 9, 25], "task_vlc": [6, 25], "sketch": 6, "demo_task_path_list_smal": 6, "apath": [6, 7], "algo": [6, 7, 10, 22, 24], "demo_custom_model": 6, "nname_argna2v": [6, 7], "my_custom_arg_nam": [6, 7], "npath_argna2v": [6, 7], "deepall_di": 6, "look": 7, "cd": 7, "demo_custom_algo_build": 7, "correspond": [7, 8, 9, 17, 19, 21], "modul": [7, 23, 24], "alreadi": 7, "builder_your": 7, "add": [7, 16, 22], "zoo_algo": [7, 10, 24], "chain": [7, 9, 11, 16, 21], "nodealgobuild": [7, 11], "lower": [7, 23], "case": [7, 9, 21], "make": [7, 21], "pull": 7, "request": [7, 11, 16, 21], "zoutput": 8, "current": [8, 17, 19, 20, 21, 22], "work": [8, 16, 25], "alter": 8, "line": [8, 9, 10, 16, 19, 21, 22, 25], "someth": [8, 9], "similar": [8, 9, 20, 25], "might": [8, 9, 16, 19], "text": [8, 9], "insid": [8, 25], "comment": 8, "aggrst": 8, "aggreg": [8, 22], "task1_test_domain1_tagnam": 8, "task2_test_domain3_tagnam": 8, "counterfactu": 8, "task1_test_domain1": 8, "saved_model": 8, "persist": [8, 22], "pytorch": [8, 17, 18, 19, 20, 21], "task1_algo1_git": 8, "commit": 8, "hashtag1_seed_1_instance_wise_predict": 8, "txt": [8, 20, 25], "wise": 8, "hashtag1_seed_1": 8, "run": [8, 17, 19, 25], "ident": [8, 17], "after": [8, 12, 14, 15, 22], "extra": [8, 17], "append": [8, 15, 21], "so": [8, 9, 16, 17, 21, 25], "conveni": 8, "compar": [8, 25], "configur": [8, 15, 21, 22, 25], "upon": [8, 18, 25], "hard": 8, "disk": [8, 12, 21], "delet": [8, 17], "complet": 8, "variou": 9, "wai": [9, 25], "accord": [9, 15, 22, 25], "indic": 9, "root": [9, 18, 21], "locat": 9, "plain": 9, "start": [9, 15, 16, 19], "should": [9, 13, 14, 16, 17, 19, 20, 22], "mode": [9, 17], "assum": [9, 12, 18, 21], "subfold": [9, 18], "give": 9, "suppos": [9, 25], "have": [9, 12, 17, 19, 20, 21, 22, 25], "car": 9, "dog": 9, "human": 9, "chair": 9, "bird": 9, "folder_a": 9, "folder_b": 9, "folder_c": 9, "sub": [9, 21], "3rd_domain": 9, "3rd": 9, "It": [9, 17], "across": [9, 13, 21, 25], "1st": 9, "hund": 9, "2nd": 9, "huski": 9, "2nd_domain": 9, "1st_domain": 9, "mensch": 9, "stuhl": 9, "vogel": 9, "drive": 9, "sit": 9, "fly": 9, "sapien": 9, "sofa": 9, "vehicl": 9, "expect": 9, "separ": 9, "function": [9, 11, 16, 17, 18, 20, 22, 23, 25], "get_task": 9, "na": 9, "none": [9, 11, 12, 16, 17, 18, 19, 20, 21, 22], "import": [9, 21, 22], "os": 9, "torchvis": [9, 16, 17, 18, 21, 22], "transform": [9, 18, 21], "mk_task_fold": [9, 21], "imsiz": [9, 21], "trans_tr": 9, "compos": 9, "resiz": 9, "224": 9, "randomresizedcrop": 9, "scale": [9, 17, 22], "randomhorizontalflip": 9, "colorjitt": 9, "randomgrayscal": 9, "totensor": 9, "normal": 9, "485": 9, "456": 9, "406": 9, "229": 9, "225": 9, "trans_t": 9, "extens": [9, 18, 21], "domain1": [9, 21], "jpg": [9, 21], "domain2": 9, "domain3": 9, "list_str_i": [9, 20, 21], "dict_domain_folder_name2class": [9, 21], "dict_domain_img_tran": [9, 21], "img_trans_t": [9, 21], "isiz": [9, 21], "dict_domain2imgroot": [9, 21], "join": 9, "taskna": [9, 21], "task_demo": 9, "call": [9, 14, 17, 20, 22, 25], "get": [9, 10, 11, 13, 16, 21], "return": [9, 11, 14, 16, 17, 18, 20, 21, 22], "print": [9, 17, 21], "__doc__": 9, "dictionari": [9, 12, 19, 20, 21, 22], "matter": [9, 21], "map": [9, 21, 22], "carri": [9, 21], "composit": [9, 21], "do": [9, 11, 13, 16, 19, 21, 25], "knowledg": [9, 21], "uniqu": [9, 21], "channel": [9, 17, 21], "height": [9, 17, 21], "width": [9, 17, 21], "absolut": [9, 21], "compo": [10, 11, 24], "matchdg_arg": [10, 11], "matchdg_bas": [10, 11], "matchdg_ctr_erm": [10, 11], "matchdg_match": [10, 11], "matchdg_util": [10, 11], "msel": [10, 11], "a_model_sel": [10, 11], "c_msel": [10, 11], "c_msel_oracl": [10, 11], "a_observ": [10, 11], "b_obvisitor": [10, 11], "c_obvisitor_cleanup": [10, 11], "c_obvisitor_gen": [10, 11], "trainer": [10, 11, 13, 14, 20, 23], "a_train": [10, 11], "args_dial": [10, 11], "train_bas": [10, 11], "train_dial": [10, 11], "train_matchdg": [10, 11], "train_visitor": [10, 11], "a_algo_build": [10, 24], "builder_custom": [10, 24], "builder_dann": [10, 24], "builder_deepal": [10, 24], "builder_di": [10, 24], "builder_diva": [10, 24], "builder_hduva": [10, 24], "builder_jigen1": [10, 24], "builder_matchdg": [10, 24], "nn_zoo": [10, 16], "net_adversari": [10, 16], "net_classif": [10, 16], "net_conv_conv_bn_pool_2": [10, 16], "net_gat": [10, 16], "nn": [10, 12, 16], "nn_alex": [10, 16], "nn_torchvis": [10, 16], "a_nn_build": [10, 24], "builder_nn_alex": [10, 24], "builder_nn_conv_bn_relu_2": [10, 24], "builder_nn_external_from_fil": [10, 24], "utils_conv_get_flat_dim": [10, 24], "zoo_nn": [10, 24], "dset": [10, 21, 24], "a_dset_mnist_color_rgb_solo": [10, 24], "dset_img_path_list": [10, 24], "dset_mnist_color_solo_default": [10, 24], "dset_poly_domains_mnist_color_default": [10, 24], "dset_subfold": [10, 24], "utils_color_palett": [10, 24], "utils_data": [10, 24], "utils_wrapdset_patch": [10, 24], "exp_protocol": [10, 24], "run_experi": [10, 24], "a_model": [10, 24], "a_model_classif": [10, 24], "args_jigen": [10, 24], "args_va": [10, 24], "model_custom": [10, 24], "model_dann": [10, 24], "model_deep_al": [10, 24], "model_diva": [10, 24], "model_hduva": [10, 24], "model_jigen": [10, 24], "model_vae_xyd_classif": [10, 24], "wrapper_matchdg": [10, 24], "a_task_classif": [10, 24], "b_task": [10, 24], "task_fold": [10, 24], "task_folder_mk": [10, 24], "task_mnist_color": [10, 24], "task_pathlist": [10, 24], "task_util": [10, 24], "utils_task": [10, 24], "utils_task_dset": [10, 24], "zoo_task": [10, 24], "util": [10, 18, 21, 24, 25], "flows_gen_img_model": [10, 24], "generate_benchmark_plot": [10, 24], "get_git_tag": [10, 24], "hyperparameter_sampl": [10, 24], "override_interfac": [10, 24], "perf": [10, 24], "perf_metr": [10, 24], "test_img": [10, 24], "u_import": [10, 24], "u_import_net_modul": [10, 24], "utils_class": [10, 24], "utils_classif": [10, 24], "utils_cuda": [10, 24], "utils_img_sav": [10, 24], "mk_parser_main": 10, "arg": [10, 11, 12, 15, 16, 17, 18, 19, 21, 22], "definit": [10, 16], "parse_cmd_arg": 10, "success_nod": 11, "abstractchainnodehandl": [11, 16, 21], "builder": [11, 16], "dset_decoration_args_algo": 11, "ddset": 11, "most": 11, "re": [11, 18, 21], "organ": [11, 21], "flow": [11, 15, 21], "like": [11, 25], "jigen": [11, 18, 20, 23], "matchdg": [11, 20, 23], "init_busi": [11, 16, 21], "exp": [11, 12, 14, 15], "initi": [11, 12, 15, 16, 19, 22], "heavi": [11, 16], "busi": [11, 16], "object": [11, 12, 13, 14, 15, 16, 20, 21, 22], "real": [11, 16], "job": [11, 16], "param": [11, 15, 16, 17, 18, 19, 21, 22], "subclass": [11, 16, 17, 20], "overrid": [11, 16, 22], "string": [11, 16, 18, 21, 22], "servic": [11, 16], "is_myjob": [11, 16, 21], "na_prefix": 11, "properti": [11, 15, 18, 20, 21, 22], "make_basic_train": 11, "class_name_model": 11, "accept": [11, 13, 14, 17, 22], "scheme": [11, 25], "nodealgobuilderdann": 11, "nodealgobuilderdeepal": 11, "nodealgobuilderdeepall_di": 11, "diva": [11, 16, 20, 23, 25], "nodealgobuilderdiva": 11, "nodealgobuilderhduva": 11, "nodealgobuilderjigen": 11, "origin": 11, "nodealgobuildermatchdg": 11, "algobuilderchainnodegett": 11, "hardcod": [11, 16, 21], "register_external_nod": 11, "add_args2parser_matchdg": 12, "parser": [12, 15, 20, 26], "matchalgobas": 12, "phi": 12, "devic": [12, 14, 15, 20, 22], "get_opt_sgd": 12, "init_erm_phas": 12, "load": [12, 19, 21], "ctr": 12, "contrast": 12, "phase": 12, "mk_match_tensor": 12, "updat": [12, 13, 14, 15], "tensor": [12, 17, 20, 22], "save_model_ctr_phas": 12, "save_model_erm_phas": 12, "get_base_domain_size4match_dg": 12, "come": [12, 25], "nomin": [12, 18], "matchctrerm": 12, "flag_erm": 12, "fals": [12, 14, 15, 16, 17, 18, 19, 20, 21, 22], "tr_epoch": [12, 15], "loader": [12, 18, 21, 22], "matchpair": 12, "i_c": [12, 16, 17, 21], "i_h": [12, 16, 17, 21, 22], "i_w": [12, 16, 17, 21], "bs_match": 12, "virtual_ref_dset_s": 12, "num_domains_tr": 12, "list_tr_domain_s": 12, "matchdictinit": 12, "val": [12, 22], "creator": 12, "get_num_row": 12, "matchdictnumdomain2sizedomain": 12, "dimens": [12, 16, 17, 20, 21, 22], "kth": 12, "size_domain_k": 12, "matchdictvirtualrefdset2eachdomain": 12, "dict": [12, 19, 22], "dist_cosine_agg": 12, "x1": 12, "x2": 12, "torch": 12, "cosinesimilar": 12, "exactli": 12, "dist_pairwise_cosin": 12, "tau": 12, "05": 12, "necesarilli": 12, "shape": 12, "want": [12, 19], "cartesian": 12, "product": 12, "pairwis": 12, "distanc": 12, "fun_tensor_norm": 12, "tensor_batch_x": 12, "amsel": 13, "tr_ob": 13, "visitor": [13, 14], "if_stop": 13, "check": [13, 15, 18, 20, 22, 25], "stop": [13, 14], "abstract": [13, 14, 15, 18, 20, 21], "decoupl": [13, 25], "mseltrloss": 13, "max_": 13, "sum": 13, "earli": 13, "best": 13, "mseloraclevisitor": 13, "acc": [13, 20, 22], "affect": 13, "how": [13, 25], "oracl": 13, "interven": 13, "innermost": 13, "interfac": [14, 20, 21, 22], "aobvisitor": 14, "invit": 14, "after_al": 14, "done": 14, "clean_up": 14, "decor": [14, 21, 22], "true": [14, 17, 18, 21, 22], "whether": [14, 17], "obvisitor": 14, "model_sel": 14, "obvisitorcleanup": 14, "obvisitorgen": 14, "abstracttrain": 15, "aconf": 15, "director": 15, "control": 15, "after_batch": 15, "ind_batch": 15, "before_tr": 15, "befor": 15, "probe": [15, 22], "post_tr": 15, "parmaet": 15, "add_args2parser_di": 15, "main": 15, "argpars": 15, "basic": [15, 21], "trainerbas": 15, "trainerdi": 15, "gen_adversari": 15, "img_natur": 15, "vec_i": [15, 20, 22], "naiv": 15, "trim": 15, "optim": [15, 17], "img": [15, 18, 22], "direct": [15, 17], "gradient": [15, 17], "necessarili": 15, "due": 15, "nonlinear": 15, "epsilon": 15, "hoc": 15, "tr_batch": 15, "anneal": 15, "trainermatchdg": 15, "ctr_model": 15, "accod": 15, "config": [15, 19, 22], "hyperscheduleran": 15, "kwarg": [15, 17], "hyperschedulerwarmup": 15, "aneal": 15, "small": 15, "par": 15, "ramp": 15, "steadi": 15, "state": 15, "total_step": 15, "set_step": 15, "gradual": 15, "chang": [15, 17, 25], "warmup": [15, 23], "par_setpoint": 15, "trainervisitor": 15, "set_schedul": 15, "schedul": 15, "flag_update_epoch": 15, "flag_update_batch": 15, "strategi": 15, "integr": 16, "respons": 16, "abstractfeatextractnnbuilderchainnod": 16, "successor_nod": 16, "ensur": [16, 19], "avoid": 16, "light": 16, "dim_out": 16, "flag_pretrain": [16, 17], "args_nnam": 16, "mknodefeatextractnnbuildernamealex": 16, "arg_name4net": 16, "arg_val": 16, "mknodefeatextractnnbuildernameconvbnrelu2": 16, "conv_strid": [16, 17], "reus": 16, "famili": 16, "regist": [16, 17], "28": 16, "mknodefeatextractnnbuilderexternfromfil": 16, "arg_name_net_path": 16, "extractor": 16, "e": [16, 17, 22, 25], "g": [16, 17, 22, 25], "get_flat_dim": 16, "i_channel": [16, 17], "batchsiz": [16, 18], "5": [16, 17, 21, 22], "flat": 16, "layer": [16, 17], "connect": [16, 17], "featextractnnbuilderchainnodegett": 16, "arg_name_of_net": 16, "arg_path_of_net": 16, "autogradfunmultipli": 17, "static": [17, 21], "backward": 17, "ctx": 17, "grad_output": 17, "formula": 17, "differenti": 17, "oper": [17, 20], "automat": 17, "alia": 17, "vjp": 17, "overridden": 17, "must": [17, 22], "context": 17, "mani": 17, "forward": [17, 20, 21], "pass": [17, 19, 22], "non": 17, "were": 17, "w": [17, 21], "r": [17, 25], "t": [17, 18], "grad": 17, "just": 17, "retriev": 17, "attribut": [17, 22, 25], "needs_input_grad": 17, "tupl": [17, 18, 19, 21], "boolean": 17, "ani": [17, 19, 25], "arbitrari": [17, 20], "though": 17, "compat": 17, "instead": 17, "either": [17, 21], "save_for_backward": 17, "thei": [17, 22], "intend": 17, "equival": 17, "save_for_forward": 17, "jvp": 17, "autogradfunreversemultipli": 17, "doc": 17, "stabl": [17, 18], "autograd": 17, "html": [17, 18], "flatten": 17, "although": 17, "recip": 17, "afterward": 17, "former": 17, "take": 17, "care": 17, "hook": 17, "latter": 17, "silent": [17, 19], "them": 17, "bool": [17, 18, 20, 22], "classifdropoutrelulinear": 17, "z_dim": 17, "target_dim": [17, 22], "appli": [17, 19, 22], "dropout": 17, "relu": 17, "linearli": 17, "activ": 17, "z_vec": 17, "netconvbnrelupool2l": 17, "dim_out_h": 17, "tensor_x": [17, 20], "netconvdens": 17, "dense_lay": 17, "custom": 17, "deep_al": 17, "until": 17, "hidden": 17, "replac": [17, 22, 25], "mk_conv_bn_relu_pool": 17, "max_pool_strid": 17, "norm": 17, "maxpool_2d": 17, "last": 17, "conv2d": 17, "input_channel": 17, "output_channel": 17, "kernel_s": 17, "stride": 17, "pad": 17, "dilat": 17, "bia": 17, "gatedconv2d": 17, "gateddens": 17, "input_s": 17, "output_s": 17, "densenet": 17, "input_flat_s": 17, "out_hidden_s": 17, "1024": 17, "last_feat_dim": 17, "4096": 17, "p_dropout": 17, "linear": 17, "layerid": 17, "alex4deepal": 17, "alexnetbas": 17, "nettorchvisionbas": 17, "sequenti": 17, "64": 17, "11": 17, "inplac": 17, "maxpool2d": 17, "ceil_mod": 17, "192": 17, "6": 17, "384": 17, "256": 17, "9": 17, "12": 17, "avgpool": 17, "adaptiveavgpool2d": 17, "p": [17, 20], "in_featur": 17, "9216": 17, "out_featur": 17, "fetch_net": 17, "alexnetnolastlay": 17, "depth": 17, "fair": 17, "comparison": 17, "fetch": [17, 18], "deleg": 17, "self": [17, 21, 22], "net_torchvis": 17, "color": [18, 21], "mnist": [18, 21], "adsetmnistcolorrgbsolo": 18, "ind_color": 18, "subset_step": 18, "color_schem": 18, "label_transform": 18, "mk_fun_label2onehot": 18, "local": [18, 21], "fun_label2onehot": 18, "list_transform": 18, "raw_split": 18, "flag_rand_color": 18, "palett": [18, 21], "rang": 18, "spectrum": 18, "subdomain": 18, "foreground": 18, "background": 18, "combin": 18, "get_background_color": 18, "ind": [18, 21], "get_foreground_color": 18, "get_num_color": 18, "dsetimpathlist": 18, "root_img": 18, "path2filelist": 18, "trans_img": 18, "trans_target": 18, "get_list_tuple_img_label": 18, "dsetmnistcolorsolodefault": 18, "merg": 18, "solo": 18, "form": [18, 25], "mix": [18, 21], "dsetmnistcolormix": 18, "n_domain": 18, "dsetmnistcolormixnodomainlabel": 18, "bb5af1d77658133af8be8c9b1a13139722315c3a": 18, "l93": 18, "_modul": 18, "datasetfold": 18, "fetch_img_path": 18, "dsetsubfold": 18, "list_class_dir": 18, "target_transform": 18, "is_valid_fil": 18, "path_dir": 18, "class_to_idx": 18, "format": 18, "i": [18, 20, 25], "len": 18, "fstring": 18, "list_tuple_path_cls_ind": 18, "has_file_allowed_extens": 18, "filenam": [18, 20, 22], "str": [18, 19, 21, 22], "lowercas": 18, "dsetinmemdecor": 18, "item": 18, "memori": 18, "fun_img_path_loader_default": 18, "discuss": 18, "handl": 18, "rgba": 18, "88428": 18, "dim": [18, 21, 22], "onehot": 18, "plot_d": 18, "f_name": 18, "32": 18, "batch_siz": [18, 20, 21, 22], "plot_ds_list": 18, "ds_list": 18, "plot": [18, 22], "fname": 18, "chosen": 18, "augment": 18, "wrapdsetpatch": 18, "num_perms2classifi": 18, "prob_no_perm": 18, "ppath": 18, "flag_do_not_weave_til": 18, "permuat": 18, "weav": 18, "get_til": 18, "ind_til": 18, "squar": 18, "hyperparamet": [19, 22, 23], "apply_dict_to_arg": 19, "flag_warn": 19, "tri": [19, 22], "unknown": 19, "long": 19, "fixm": 19, "realli": 19, "got": 19, "load_paramet": 19, "int": [19, 21, 22], "param_fil": 19, "param_index": [19, 22], "out_fil": 19, "start_se": 19, "misc": 19, "test_domain": 19, "startse": 19, "endse": 19, "evalu": [19, 20, 21, 25], "benchmark": [19, 22, 25], "cover": 19, "panda": 19, "datafram": [19, 22], "option": [19, 20, 21, 22], "commandlin": [19, 20], "kind": 20, "amodel": 20, "segment": 20, "seq2seq": 20, "cal_loss": 20, "tensor_i": 20, "tensor_d": 20, "calcul": 20, "cal_reg_loss": 20, "regular": [20, 25], "cal_task_loss": 20, "claasif": 20, "amodelclassif": 20, "list_d_tr": 20, "cal_logit_i": 20, "logit": [20, 22], "softmax": 20, "cal_loss_gen_adv": 20, "x_natur": 20, "x_adv": 20, "cal_perf_metr": 20, "loader_tr": [20, 21], "loader_t": [20, 21, 22], "matric": 20, "could": [20, 25], "modifi": 20, "necessari": 20, "create_perf_obj": 20, "target": [20, 21], "quieri": 20, "embed": [20, 22], "cal": 20, "infer_y_vpicn": 20, "vpicn": 20, "v": 20, "vector": [20, 21, 22], "c": [20, 21], "confid": 20, "maximum": [20, 22], "match_feat_fun_na": 20, "pred2fil": 20, "path_predict": 20, "flag_pred_scalar": 20, "dump": 20, "saniti": 20, "add_args2parser_jigen": 20, "add_args2parser_va": 20, "amodelcustom": 20, "list_str_d": 20, "dict_net_module_na2arg_na": 20, "being": 20, "mk_dann": 20, "parent_class": 20, "instanti": [20, 22], "dan": 20, "determin": [20, 22], "inherit": 20, "parent": 20, "modeldan": 20, "mk_deepal": 20, "deepal": [20, 23], "modeldeepall": 20, "mk_diva": 20, "vaexydclassif": 20, "mk_hduva": 20, "dann": [20, 23], "mk_jigen": 20, "modeljigen": 20, "xyd": 20, "chain_node_build": 20, "init_p_zx4batch": 20, "wrapper": 20, "conform": 20, "modelwrapmatchdglogit": 20, "wrap": [20, 21], "taskclassif": 21, "nodetaskdgclassif": 21, "succ": 21, "get_list_domain": 21, "than": 21, "get_list_domains_tr_t": 21, "tr_id": 21, "te_id": 21, "dg": 21, "id": 21, "complement": 21, "get_na": 21, "na_tr": 21, "na_t": 21, "resampl": 21, "domain_na_t": 21, "list_domain_tr": 21, "getter": 21, "loader_v": 21, "sample_sav": 21, "subfolder_na": [21, 22], "task_sampl": 21, "task_nam": [21, 22], "nodetaskdict": 21, "count_domain_class": 21, "iter": [21, 22], "count": 21, "doubl": 21, "class1": 21, "class2": 21, "decorate_dset": 21, "dispatch": 21, "get_dset_by_domain": 21, "na_domain": 21, "set_list_domain": 21, "list_domain": 21, "setter": 21, "_list_domain": 21, "when": 21, "nodetaskfold": 21, "xx": 21, "yy": 21, "zz": 21, "nodetaskfolderclassnamismatch": 21, "jpeg": 21, "png": 21, "nodetaskmnistcolor10": 21, "deafult": 21, "zero": 21, "statement": 21, "otherwis": [21, 22], "taskpathlist": 21, "consist": 21, "pair": 21, "slot": 21, "know": 21, "second": 21, "numer": [21, 22], "nodetaskpathlistdummi": 21, "mk_node_task_path_list": 21, "trans4al": 21, "dict_class_label2nam": 21, "dict_d2filepath_list_img": 21, "dict_d2filepath_list_img_v": 21, "dict_d2filepath_list_img_t": 21, "parse_domain_id": 21, "list_domain_id": 21, "avail": [21, 25], "around": 21, "dsetclassvecdecor": 21, "dict_folder_name2class_glob": 21, "fun_class_local_na2vec_new": 21, "k": 21, "straight": 21, "dsetclassvecdecoratorimgpath": 21, "dsetdomainvecdecor": 21, "vec_domain": 21, "dsetdomainvecdecoratorimgpath": 21, "except": 21, "mostli": [21, 25], "h": [21, 25], "loaderdomainlabel": 21, "dim_d": 21, "img_loader2dir": 21, "list_domain_na": 21, "list_class_na": 21, "specul": 21, "correct": [21, 22], "assumend": 21, "mk_loader": 21, "bsize": 21, "drop_last": 21, "mk_onehot": 21, "tensor1hot2ind": 21, "tensor_label": 21, "dsetinddecorator4xyd": 21, "wih": 21, "taskchainnodegett": 21, "flowgenimg": 22, "gen_img_load": 22, "gen_img_xyd": 22, "vec_d": 22, "folder_na": 22, "fun_gen": 22, "output_folder_na": 22, "gen_bencmark_plot": 22, "gen_benchmark_plot": 22, "agg_result": 22, "output_dir": 22, "restult": 22, "column": 22, "epo": 22, "intrepret": 22, "precis": 22, "recal": 22, "f1": 22, "auroc": 22, "gen_plot": 22, "max_0_x": 22, "x_arg": 22, "max": 22, "radar_plot": 22, "dataframe_in": 22, "distinguish_hyperparam": 22, "obj1": 22, "obj2": 22, "distinguish_param_setup": 22, "distinguish": 22, "round_vals_in_dict": 22, "df_column_in": 22, "signific": 22, "digit": 22, "hyperparam": 22, "scatterplot": 22, "obj": 22, "kde": 22, "point": 22, "estim": [22, 25], "scatterplot_matrix": 22, "reg": 22, "regress": 22, "over": 22, "print_diff": 22, "categoricalhyperparamet": 22, "datatyp": 22, "step": 22, "p1": 22, "integ": 22, "els": 22, "float": 22, "min": 22, "p2": 22, "get_val": 22, "referencehyperparamet": 22, "thu": [22, 25], "sampledhyperparamet": 22, "check_constraint": 22, "fulfil": 22, "get_hyperparamet": 22, "factori": 22, "is_task": 22, "sample_hyperparamet": 22, "dest": 22, "full": 22, "explicitli": 22, "trust": 22, "sample_paramet": 22, "10_0000": 22, "attempt": 22, "compli": 22, "sample_task": 22, "num_sampl": 22, "sample_df": 22, "interface_class": 22, "go": 22, "nearest": 22, "method2overrid": 22, "child": 22, "baseclass": 22, "fun": 22, "perfclassif": 22, "classmethod": 22, "cal_acc": 22, "max_batch": 22, "gpu": 22, "less": 22, "burden": 22, "travers": 22, "whole": 22, "gen_fun_acc": 22, "dim_target": 22, "perfmetricclassif": 22, "num_class": 22, "averag": 22, "macro": 22, "metric": 22, "cal_metr": 22, "mk_img": 22, "i_ch": 22, "mk_rand_label_onehot": 22, "mk_rand_xyd": 22, "im": 22, "y_dim": 22, "d_dim": 22, "import_path": 22, "extern": 22, "build_external_obj_net_module_feat_extract": 22, "mpath": 22, "fine": 22, "problemat": 22, "store_arg": 22, "get_label_na": 22, "tensor_ind": 22, "list_str_na": 22, "logit2preds_vp": 22, "mk_dummy_label_list_str": 22, "prefix": [22, 25], "get_devic": 22, "flag_no_cu": 22, "mk_fun_sav_img": 22, "nrow": 22, "saver": 22, "sav_add_titl": 22, "grid_img": 22, "matplotlib": 22, "pyplot": 22, "subpackag": [23, 24], "submodul": [23, 24], "arg_pars": [23, 24], "overview": 23, "hduva": 23, "dial": 23, "FOR": 23, "evid": 23, "bound": 23, "search": 23, "page": 23, "content": 24, "aim": 25, "multipl": 25, "unseen": 25, "try": 25, "emper": 25, "left": 25, "rest": 25, "onc": 25, "came": 25, "claim": 25, "ever": 25, "wonder": 25, "Is": 25, "power": 25, "happen": 25, "backbon": 25, "protocol": 25, "Will": 25, "my": 25, "clever": 25, "special": 25, "maxim": 25, "factor": 25, "wa": 25, "keep": 25, "underli": 25, "transpar": 25, "concret": 25, "plugin": 25, "discret": 25, "fairli": 25, "simpli": 25, "poetri": 25, "read": 25, "Or": 25, "depend": 25, "pip": 25, "clone": 25, "readi": 25, "toi": 25, "basi": 25, "restrain": 25, "help": 25, "own": 25, "generl": 25, "contibut": 25, "linkifi": 26, "m2r2": 26, "myst": 26, "rinohtyp": 26, "nbsphinx": 26, "nbsphinx_link": 26, "sphinx_materi": 26, "commonmark": 26, "git": 26, "rtfd": 26}, "objects": {"": [[10, 0, 0, "-", "domainlab"]], "domainlab": [[11, 0, 0, "-", "algos"], [10, 0, 0, "-", "arg_parser"], [16, 0, 0, "-", "compos"], [18, 0, 0, "-", "dsets"], [19, 0, 0, "-", "exp_protocol"], [20, 0, 0, "-", "models"], [21, 0, 0, "-", "tasks"], [22, 0, 0, "-", "utils"]], "domainlab.algos": [[11, 0, 0, "-", "a_algo_builder"], [11, 0, 0, "-", "builder_custom"], [11, 0, 0, "-", "builder_dann"], [11, 0, 0, "-", "builder_deepall"], [11, 0, 0, "-", "builder_dial"], [11, 0, 0, "-", "builder_diva"], [11, 0, 0, "-", "builder_hduva"], [11, 0, 0, "-", "builder_jigen1"], [11, 0, 0, "-", "builder_matchdg"], [12, 0, 0, "-", "compos"], [13, 0, 0, "-", "msels"], [14, 0, 0, "-", "observers"], [15, 0, 0, "-", "trainers"], [11, 0, 0, "-", "zoo_algos"]], "domainlab.algos.a_algo_builder": [[11, 1, 1, "", "NodeAlgoBuilder"]], "domainlab.algos.a_algo_builder.NodeAlgoBuilder": [[11, 2, 1, "", "dset_decoration_args_algo"], [11, 2, 1, "", "init_business"], [11, 2, 1, "", "is_myjob"], [11, 3, 1, "", "na_prefix"], [11, 4, 1, "", "name"]], "domainlab.algos.builder_custom": [[11, 5, 1, "", "make_basic_trainer"]], "domainlab.algos.builder_dann": [[11, 1, 1, "", "NodeAlgoBuilderDANN"]], "domainlab.algos.builder_dann.NodeAlgoBuilderDANN": [[11, 2, 1, "", "init_business"]], "domainlab.algos.builder_deepall": [[11, 1, 1, "", "NodeAlgoBuilderDeepAll"]], "domainlab.algos.builder_deepall.NodeAlgoBuilderDeepAll": [[11, 2, 1, "", "init_business"]], "domainlab.algos.builder_dial": [[11, 1, 1, "", "NodeAlgoBuilderDeepAll_DIAL"]], "domainlab.algos.builder_dial.NodeAlgoBuilderDeepAll_DIAL": [[11, 2, 1, "", "init_business"]], "domainlab.algos.builder_diva": [[11, 1, 1, "", "NodeAlgoBuilderDIVA"]], "domainlab.algos.builder_diva.NodeAlgoBuilderDIVA": [[11, 2, 1, "", "init_business"]], "domainlab.algos.builder_hduva": [[11, 1, 1, "", "NodeAlgoBuilderHDUVA"]], "domainlab.algos.builder_hduva.NodeAlgoBuilderHDUVA": [[11, 2, 1, "", "init_business"]], "domainlab.algos.builder_jigen1": [[11, 1, 1, "", "NodeAlgoBuilderJiGen"]], "domainlab.algos.builder_jigen1.NodeAlgoBuilderJiGen": [[11, 2, 1, "", "dset_decoration_args_algo"], [11, 2, 1, "", "init_business"]], "domainlab.algos.builder_matchdg": [[11, 1, 1, "", "NodeAlgoBuilderMatchDG"]], "domainlab.algos.builder_matchdg.NodeAlgoBuilderMatchDG": [[11, 2, 1, "", "dset_decoration_args_algo"], [11, 2, 1, "", "init_business"]], "domainlab.algos.compos": [[12, 0, 0, "-", "matchdg_args"], [12, 0, 0, "-", "matchdg_base"], [12, 0, 0, "-", "matchdg_ctr_erm"], [12, 0, 0, "-", "matchdg_match"], [12, 0, 0, "-", "matchdg_utils"]], "domainlab.algos.compos.matchdg_args": [[12, 5, 1, "", "add_args2parser_matchdg"]], "domainlab.algos.compos.matchdg_base": [[12, 1, 1, "", "MatchAlgoBase"], [12, 5, 1, "", "get_base_domain_size4match_dg"]], "domainlab.algos.compos.matchdg_base.MatchAlgoBase": [[12, 2, 1, "", "get_opt_sgd"], [12, 2, 1, "", "init_erm_phase"], [12, 2, 1, "", "mk_match_tensor"], [12, 2, 1, "", "save_model_ctr_phase"], [12, 2, 1, "", "save_model_erm_phase"]], "domainlab.algos.compos.matchdg_ctr_erm": [[12, 1, 1, "", "MatchCtrErm"]], "domainlab.algos.compos.matchdg_ctr_erm.MatchCtrErm": [[12, 2, 1, "", "tr_epoch"], [12, 2, 1, "", "train"]], "domainlab.algos.compos.matchdg_match": [[12, 1, 1, "", "MatchPair"]], "domainlab.algos.compos.matchdg_utils": [[12, 1, 1, "", "MatchDictInit"], [12, 1, 1, "", "MatchDictNumDomain2SizeDomain"], [12, 1, 1, "", "MatchDictVirtualRefDset2EachDomain"], [12, 5, 1, "", "dist_cosine_agg"], [12, 5, 1, "", "dist_pairwise_cosine"], [12, 5, 1, "", "fun_tensor_normalize"]], "domainlab.algos.compos.matchdg_utils.MatchDictInit": [[12, 2, 1, "", "get_num_rows"]], "domainlab.algos.compos.matchdg_utils.MatchDictNumDomain2SizeDomain": [[12, 2, 1, "", "get_num_rows"]], "domainlab.algos.compos.matchdg_utils.MatchDictVirtualRefDset2EachDomain": [[12, 2, 1, "", "get_num_rows"]], "domainlab.algos.msels": [[13, 0, 0, "-", "a_model_sel"], [13, 0, 0, "-", "c_msel"], [13, 0, 0, "-", "c_msel_oracle"]], "domainlab.algos.msels.a_model_sel": [[13, 1, 1, "", "AMSel"]], "domainlab.algos.msels.a_model_sel.AMSel": [[13, 2, 1, "", "accept"], [13, 2, 1, "", "if_stop"], [13, 2, 1, "", "update"]], "domainlab.algos.msels.c_msel": [[13, 1, 1, "", "MSelTrLoss"]], "domainlab.algos.msels.c_msel.MSelTrLoss": [[13, 2, 1, "", "if_stop"], [13, 2, 1, "", "update"]], "domainlab.algos.msels.c_msel_oracle": [[13, 1, 1, "", "MSelOracleVisitor"]], "domainlab.algos.msels.c_msel_oracle.MSelOracleVisitor": [[13, 2, 1, "", "accept"], [13, 2, 1, "", "if_stop"], [13, 2, 1, "", "update"]], "domainlab.algos.observers": [[14, 0, 0, "-", "a_observer"], [14, 0, 0, "-", "b_obvisitor"], [14, 0, 0, "-", "c_obvisitor_cleanup"], [14, 0, 0, "-", "c_obvisitor_gen"]], "domainlab.algos.observers.a_observer": [[14, 1, 1, "", "AObVisitor"]], "domainlab.algos.observers.a_observer.AObVisitor": [[14, 2, 1, "", "accept"], [14, 2, 1, "", "after_all"], [14, 2, 1, "", "clean_up"], [14, 2, 1, "", "update"]], "domainlab.algos.observers.b_obvisitor": [[14, 1, 1, "", "ObVisitor"]], "domainlab.algos.observers.b_obvisitor.ObVisitor": [[14, 2, 1, "", "accept"], [14, 2, 1, "", "after_all"], [14, 2, 1, "", "clean_up"], [14, 2, 1, "", "update"]], "domainlab.algos.observers.c_obvisitor_cleanup": [[14, 1, 1, "", "ObVisitorCleanUp"]], "domainlab.algos.observers.c_obvisitor_cleanup.ObVisitorCleanUp": [[14, 2, 1, "", "accept"], [14, 2, 1, "", "after_all"], [14, 2, 1, "", "clean_up"], [14, 2, 1, "", "update"]], "domainlab.algos.observers.c_obvisitor_gen": [[14, 1, 1, "", "ObVisitorGen"]], "domainlab.algos.observers.c_obvisitor_gen.ObVisitorGen": [[14, 2, 1, "", "after_all"]], "domainlab.algos.trainers": [[15, 0, 0, "-", "a_trainer"], [15, 0, 0, "-", "args_dial"], [15, 0, 0, "-", "train_basic"], [15, 0, 0, "-", "train_dial"], [15, 0, 0, "-", "train_matchdg"], [15, 0, 0, "-", "train_visitor"]], "domainlab.algos.trainers.a_trainer": [[15, 1, 1, "", "AbstractTrainer"]], "domainlab.algos.trainers.a_trainer.AbstractTrainer": [[15, 2, 1, "", "after_batch"], [15, 2, 1, "", "before_tr"], [15, 2, 1, "", "post_tr"], [15, 2, 1, "", "tr_epoch"]], "domainlab.algos.trainers.args_dial": [[15, 5, 1, "", "add_args2parser_dial"]], "domainlab.algos.trainers.train_basic": [[15, 1, 1, "", "TrainerBasic"]], "domainlab.algos.trainers.train_basic.TrainerBasic": [[15, 2, 1, "", "before_tr"], [15, 2, 1, "", "tr_epoch"]], "domainlab.algos.trainers.train_dial": [[15, 1, 1, "", "TrainerDIAL"]], "domainlab.algos.trainers.train_dial.TrainerDIAL": [[15, 2, 1, "", "gen_adversarial"], [15, 2, 1, "", "tr_batch"], [15, 2, 1, "", "tr_epoch"]], "domainlab.algos.trainers.train_matchdg": [[15, 1, 1, "", "TrainerMatchDG"]], "domainlab.algos.trainers.train_matchdg.TrainerMatchDG": [[15, 2, 1, "", "before_tr"], [15, 2, 1, "", "tr_epoch"]], "domainlab.algos.trainers.train_visitor": [[15, 1, 1, "", "HyperSchedulerAneal"], [15, 1, 1, "", "HyperSchedulerWarmup"], [15, 1, 1, "", "TrainerVisitor"]], "domainlab.algos.trainers.train_visitor.HyperSchedulerAneal": [[15, 2, 1, "", "aneal"]], "domainlab.algos.trainers.train_visitor.HyperSchedulerWarmup": [[15, 2, 1, "", "set_steps"], [15, 2, 1, "", "warmup"]], "domainlab.algos.trainers.train_visitor.TrainerVisitor": [[15, 2, 1, "", "after_batch"], [15, 2, 1, "", "before_tr"], [15, 2, 1, "", "set_scheduler"], [15, 2, 1, "", "tr_batch"], [15, 2, 1, "", "tr_epoch"]], "domainlab.algos.zoo_algos": [[11, 1, 1, "", "AlgoBuilderChainNodeGetter"]], "domainlab.algos.zoo_algos.AlgoBuilderChainNodeGetter": [[11, 2, 1, "", "register_external_node"]], "domainlab.arg_parser": [[10, 5, 1, "", "mk_parser_main"], [10, 5, 1, "", "parse_cmd_args"]], "domainlab.compos": [[16, 0, 0, "-", "a_nn_builder"], [16, 0, 0, "-", "builder_nn_alex"], [16, 0, 0, "-", "builder_nn_conv_bn_relu_2"], [16, 0, 0, "-", "builder_nn_external_from_file"], [17, 0, 0, "-", "nn_zoo"], [16, 0, 0, "-", "utils_conv_get_flat_dim"], [16, 0, 0, "-", "zoo_nn"]], "domainlab.compos.a_nn_builder": [[16, 1, 1, "", "AbstractFeatExtractNNBuilderChainNode"]], "domainlab.compos.a_nn_builder.AbstractFeatExtractNNBuilderChainNode": [[16, 2, 1, "", "init_business"], [16, 2, 1, "", "is_myjob"]], "domainlab.compos.builder_nn_alex": [[16, 5, 1, "", "mkNodeFeatExtractNNBuilderNameAlex"]], "domainlab.compos.builder_nn_conv_bn_relu_2": [[16, 5, 1, "", "mkNodeFeatExtractNNBuilderNameConvBnRelu2"]], "domainlab.compos.builder_nn_external_from_file": [[16, 5, 1, "", "mkNodeFeatExtractNNBuilderExternFromFile"]], "domainlab.compos.nn_zoo": [[17, 0, 0, "-", "net_adversarial"], [17, 0, 0, "-", "net_classif"], [17, 0, 0, "-", "net_conv_conv_bn_pool_2"], [17, 0, 0, "-", "net_gated"], [17, 0, 0, "-", "nn"], [17, 0, 0, "-", "nn_alex"], [17, 0, 0, "-", "nn_torchvision"]], "domainlab.compos.nn_zoo.net_adversarial": [[17, 1, 1, "", "AutoGradFunMultiply"], [17, 1, 1, "", "AutoGradFunReverseMultiply"], [17, 1, 1, "", "Flatten"]], "domainlab.compos.nn_zoo.net_adversarial.AutoGradFunMultiply": [[17, 2, 1, "", "backward"], [17, 2, 1, "", "forward"]], "domainlab.compos.nn_zoo.net_adversarial.AutoGradFunReverseMultiply": [[17, 2, 1, "", "backward"], [17, 2, 1, "", "forward"]], "domainlab.compos.nn_zoo.net_adversarial.Flatten": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.net_classif": [[17, 1, 1, "", "ClassifDropoutReluLinear"]], "domainlab.compos.nn_zoo.net_classif.ClassifDropoutReluLinear": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2": [[17, 1, 1, "", "NetConvBnReluPool2L"], [17, 1, 1, "", "NetConvDense"], [17, 5, 1, "", "mk_conv_bn_relu_pool"]], "domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2.NetConvBnReluPool2L": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2.NetConvDense": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.net_gated": [[17, 1, 1, "", "Conv2d"], [17, 1, 1, "", "GatedConv2d"], [17, 1, 1, "", "GatedDense"]], "domainlab.compos.nn_zoo.net_gated.Conv2d": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.net_gated.GatedConv2d": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.net_gated.GatedDense": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.nn": [[17, 1, 1, "", "DenseNet"], [17, 1, 1, "", "LayerId"]], "domainlab.compos.nn_zoo.nn.DenseNet": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.nn.LayerId": [[17, 2, 1, "", "forward"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.nn_alex": [[17, 1, 1, "", "Alex4DeepAll"], [17, 1, 1, "", "AlexNetBase"], [17, 1, 1, "", "AlexNetNoLastLayer"]], "domainlab.compos.nn_zoo.nn_alex.Alex4DeepAll": [[17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.nn_alex.AlexNetBase": [[17, 2, 1, "", "fetch_net"], [17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.nn_alex.AlexNetNoLastLayer": [[17, 3, 1, "", "training"]], "domainlab.compos.nn_zoo.nn_torchvision": [[17, 1, 1, "", "NetTorchVisionBase"]], "domainlab.compos.nn_zoo.nn_torchvision.NetTorchVisionBase": [[17, 2, 1, "", "fetch_net"], [17, 2, 1, "", "forward"], [17, 2, 1, "", "show"], [17, 3, 1, "", "training"]], "domainlab.compos.utils_conv_get_flat_dim": [[16, 5, 1, "", "get_flat_dim"]], "domainlab.compos.zoo_nn": [[16, 1, 1, "", "FeatExtractNNBuilderChainNodeGetter"]], "domainlab.dsets": [[18, 0, 0, "-", "a_dset_mnist_color_rgb_solo"], [18, 0, 0, "-", "dset_img_path_list"], [18, 0, 0, "-", "dset_mnist_color_solo_default"], [18, 0, 0, "-", "dset_poly_domains_mnist_color_default"], [18, 0, 0, "-", "dset_subfolder"], [18, 0, 0, "-", "utils_color_palette"], [18, 0, 0, "-", "utils_data"], [18, 0, 0, "-", "utils_wrapdset_patches"]], "domainlab.dsets.a_dset_mnist_color_rgb_solo": [[18, 1, 1, "", "ADsetMNISTColorRGBSolo"]], "domainlab.dsets.a_dset_mnist_color_rgb_solo.ADsetMNISTColorRGBSolo": [[18, 2, 1, "", "get_background_color"], [18, 2, 1, "", "get_foreground_color"], [18, 2, 1, "", "get_num_colors"]], "domainlab.dsets.dset_img_path_list": [[18, 1, 1, "", "DsetImPathList"]], "domainlab.dsets.dset_img_path_list.DsetImPathList": [[18, 2, 1, "", "get_list_tuple_img_label"]], "domainlab.dsets.dset_mnist_color_solo_default": [[18, 1, 1, "", "DsetMNISTColorSoloDefault"]], "domainlab.dsets.dset_mnist_color_solo_default.DsetMNISTColorSoloDefault": [[18, 2, 1, "", "get_background_color"], [18, 2, 1, "", "get_foreground_color"], [18, 2, 1, "", "get_num_colors"], [18, 4, 1, "", "palette"]], "domainlab.dsets.dset_poly_domains_mnist_color_default": [[18, 1, 1, "", "DsetMNISTColorMix"], [18, 1, 1, "", "DsetMNISTColorMixNoDomainLabel"]], "domainlab.dsets.dset_subfolder": [[18, 1, 1, "", "DsetSubFolder"], [18, 5, 1, "", "fetch_img_paths"], [18, 5, 1, "", "has_file_allowed_extension"]], "domainlab.dsets.utils_data": [[18, 1, 1, "", "DsetInMemDecorator"], [18, 5, 1, "", "fun_img_path_loader_default"], [18, 5, 1, "", "mk_fun_label2onehot"], [18, 5, 1, "", "plot_ds"], [18, 5, 1, "", "plot_ds_list"]], "domainlab.dsets.utils_wrapdset_patches": [[18, 1, 1, "", "WrapDsetPatches"]], "domainlab.dsets.utils_wrapdset_patches.WrapDsetPatches": [[18, 2, 1, "", "get_tile"]], "domainlab.exp_protocol": [[19, 0, 0, "-", "run_experiment"]], "domainlab.exp_protocol.run_experiment": [[19, 5, 1, "", "apply_dict_to_args"], [19, 5, 1, "", "load_parameters"], [19, 5, 1, "", "run_experiment"]], "domainlab.models": [[20, 0, 0, "-", "a_model"], [20, 0, 0, "-", "a_model_classif"], [20, 0, 0, "-", "args_jigen"], [20, 0, 0, "-", "args_vae"], [20, 0, 0, "-", "model_custom"], [20, 0, 0, "-", "model_dann"], [20, 0, 0, "-", "model_deep_all"], [20, 0, 0, "-", "model_diva"], [20, 0, 0, "-", "model_hduva"], [20, 0, 0, "-", "model_jigen"], [20, 0, 0, "-", "model_vae_xyd_classif"], [20, 0, 0, "-", "wrapper_matchdg"]], "domainlab.models.a_model": [[20, 1, 1, "", "AModel"]], "domainlab.models.a_model.AModel": [[20, 2, 1, "", "cal_loss"], [20, 2, 1, "", "cal_reg_loss"], [20, 2, 1, "", "cal_task_loss"], [20, 2, 1, "", "forward"], [20, 3, 1, "", "training"]], "domainlab.models.a_model_classif": [[20, 1, 1, "", "AModelClassif"]], "domainlab.models.a_model_classif.AModelClassif": [[20, 2, 1, "", "cal_logit_y"], [20, 2, 1, "", "cal_loss_gen_adv"], [20, 2, 1, "", "cal_perf_metric"], [20, 2, 1, "", "cal_reg_loss"], [20, 2, 1, "", "cal_task_loss"], [20, 2, 1, "", "create_perf_obj"], [20, 4, 1, "", "dim_y"], [20, 2, 1, "", "evaluate"], [20, 2, 1, "", "infer_y_vpicn"], [20, 3, 1, "", "match_feat_fun_na"], [20, 2, 1, "", "pred2file"], [20, 3, 1, "", "training"]], "domainlab.models.args_jigen": [[20, 5, 1, "", "add_args2parser_jigen"]], "domainlab.models.args_vae": [[20, 5, 1, "", "add_args2parser_vae"]], "domainlab.models.model_custom": [[20, 1, 1, "", "AModelCustom"]], "domainlab.models.model_custom.AModelCustom": [[20, 2, 1, "", "cal_logit_y"], [20, 4, 1, "", "dict_net_module_na2arg_na"], [20, 2, 1, "", "infer_y_vpicn"], [20, 3, 1, "", "training"]], "domainlab.models.model_dann": [[20, 5, 1, "", "mk_dann"]], "domainlab.models.model_deep_all": [[20, 5, 1, "", "mk_deepall"]], "domainlab.models.model_diva": [[20, 5, 1, "", "mk_diva"]], "domainlab.models.model_hduva": [[20, 5, 1, "", "mk_hduva"]], "domainlab.models.model_jigen": [[20, 5, 1, "", "mk_jigen"]], "domainlab.models.model_vae_xyd_classif": [[20, 1, 1, "", "VAEXYDClassif"]], "domainlab.models.model_vae_xyd_classif.VAEXYDClassif": [[20, 2, 1, "", "cal_logit_y"], [20, 2, 1, "", "init_p_zx4batch"], [20, 3, 1, "", "training"]], "domainlab.models.wrapper_matchdg": [[20, 1, 1, "", "ModelWrapMatchDGLogit"]], "domainlab.models.wrapper_matchdg.ModelWrapMatchDGLogit": [[20, 2, 1, "", "cal_logit_y"], [20, 2, 1, "", "cal_loss"], [20, 2, 1, "", "cal_reg_loss"], [20, 2, 1, "", "forward"], [20, 3, 1, "", "training"]], "domainlab.tasks": [[21, 0, 0, "-", "a_task_classif"], [21, 0, 0, "-", "b_task"], [21, 0, 0, "-", "task_folder"], [21, 0, 0, "-", "task_folder_mk"], [21, 0, 0, "-", "task_mnist_color"], [21, 0, 0, "-", "task_pathlist"], [21, 0, 0, "-", "task_utils"], [21, 0, 0, "-", "utils_task"], [21, 0, 0, "-", "utils_task_dset"], [21, 0, 0, "-", "zoo_tasks"]], "domainlab.tasks.a_task_classif": [[21, 1, 1, "", "NodeTaskDGClassif"]], "domainlab.tasks.a_task_classif.NodeTaskDGClassif": [[21, 4, 1, "", "dim_y"], [21, 2, 1, "", "get_list_domains"], [21, 2, 1, "", "get_list_domains_tr_te"], [21, 2, 1, "", "get_na"], [21, 2, 1, "", "init_business"], [21, 2, 1, "", "is_myjob"], [21, 4, 1, "", "isize"], [21, 4, 1, "", "list_domain_tr"], [21, 4, 1, "", "list_str_y"], [21, 4, 1, "", "loader_te"], [21, 4, 1, "", "loader_tr"], [21, 4, 1, "", "loader_val"], [21, 2, 1, "", "sample_sav"], [21, 4, 1, "", "task_name"]], "domainlab.tasks.b_task": [[21, 1, 1, "", "NodeTaskDict"]], "domainlab.tasks.b_task.NodeTaskDict": [[21, 2, 1, "", "count_domain_class"], [21, 2, 1, "", "decorate_dset"], [21, 2, 1, "", "get_dset_by_domain"], [21, 2, 1, "", "get_list_domains"], [21, 2, 1, "", "init_business"], [21, 4, 1, "", "isize"], [21, 4, 1, "", "list_str_y"], [21, 2, 1, "", "set_list_domains"]], "domainlab.tasks.task_folder": [[21, 1, 1, "", "NodeTaskFolder"], [21, 1, 1, "", "NodeTaskFolderClassNaMismatch"]], "domainlab.tasks.task_folder.NodeTaskFolder": [[21, 4, 1, "", "dict_domain2imgroot"], [21, 4, 1, "", "extensions"], [21, 2, 1, "", "get_dset_by_domain"]], "domainlab.tasks.task_folder.NodeTaskFolderClassNaMismatch": [[21, 2, 1, "", "get_dset_by_domain"]], "domainlab.tasks.task_folder_mk": [[21, 5, 1, "", "mk_task_folder"]], "domainlab.tasks.task_mnist_color": [[21, 1, 1, "", "NodeTaskMNISTColor10"]], "domainlab.tasks.task_mnist_color.NodeTaskMNISTColor10": [[21, 2, 1, "", "get_dset_by_domain"], [21, 2, 1, "", "get_list_domains"], [21, 4, 1, "", "isize"], [21, 4, 1, "", "list_str_y"]], "domainlab.tasks.task_pathlist": [[21, 1, 1, "", "NodeTaskPathListDummy"], [21, 5, 1, "", "mk_node_task_path_list"]], "domainlab.tasks.task_utils": [[21, 5, 1, "", "parse_domain_id"]], "domainlab.tasks.utils_task": [[21, 1, 1, "", "DsetClassVecDecorator"], [21, 1, 1, "", "DsetClassVecDecoratorImgPath"], [21, 1, 1, "", "DsetDomainVecDecorator"], [21, 1, 1, "", "DsetDomainVecDecoratorImgPath"], [21, 1, 1, "", "ImSize"], [21, 1, 1, "", "LoaderDomainLabel"], [21, 5, 1, "", "img_loader2dir"], [21, 5, 1, "", "mk_loader"], [21, 5, 1, "", "mk_onehot"], [21, 5, 1, "", "tensor1hot2ind"]], "domainlab.tasks.utils_task.DsetClassVecDecorator": [[21, 2, 1, "", "fun_class_local_na2vec_new"], [21, 4, 1, "", "targets"]], "domainlab.tasks.utils_task.DsetDomainVecDecorator": [[21, 4, 1, "", "targets"]], "domainlab.tasks.utils_task.ImSize": [[21, 4, 1, "", "c"], [21, 4, 1, "", "h"], [21, 4, 1, "", "w"]], "domainlab.tasks.utils_task_dset": [[21, 1, 1, "", "DsetIndDecorator4XYD"]], "domainlab.tasks.zoo_tasks": [[21, 1, 1, "", "TaskChainNodeGetter"]], "domainlab.utils": [[22, 0, 0, "-", "flows_gen_img_model"], [22, 0, 0, "-", "generate_benchmark_plots"], [22, 0, 0, "-", "get_git_tag"], [22, 0, 0, "-", "hyperparameter_sampling"], [22, 0, 0, "-", "override_interface"], [22, 0, 0, "-", "perf"], [22, 0, 0, "-", "perf_metrics"], [22, 0, 0, "-", "test_img"], [22, 0, 0, "-", "u_import"], [22, 0, 0, "-", "u_import_net_module"], [22, 0, 0, "-", "utils_class"], [22, 0, 0, "-", "utils_classif"], [22, 0, 0, "-", "utils_cuda"], [22, 0, 0, "-", "utils_img_sav"]], "domainlab.utils.flows_gen_img_model": [[22, 1, 1, "", "FlowGenImgs"], [22, 5, 1, "", "fun_gen"]], "domainlab.utils.flows_gen_img_model.FlowGenImgs": [[22, 2, 1, "", "gen_img_loader"], [22, 2, 1, "", "gen_img_xyd"]], "domainlab.utils.generate_benchmark_plots": [[22, 5, 1, "", "gen_benchmark_plots"], [22, 5, 1, "", "gen_plots"], [22, 5, 1, "", "max_0_x"], [22, 5, 1, "", "radar_plot"], [22, 5, 1, "", "round_vals_in_dict"], [22, 5, 1, "", "scatterplot"], [22, 5, 1, "", "scatterplot_matrix"]], "domainlab.utils.get_git_tag": [[22, 5, 1, "", "get_git_tag"]], "domainlab.utils.hyperparameter_sampling": [[22, 1, 1, "", "CategoricalHyperparameter"], [22, 1, 1, "", "Hyperparameter"], [22, 1, 1, "", "ReferenceHyperparameter"], [22, 1, 1, "", "SampledHyperparameter"], [22, 5, 1, "", "check_constraints"], [22, 5, 1, "", "get_hyperparameter"], [22, 5, 1, "", "is_task"], [22, 5, 1, "", "sample_hyperparameters"], [22, 5, 1, "", "sample_parameters"], [22, 5, 1, "", "sample_task"]], "domainlab.utils.hyperparameter_sampling.CategoricalHyperparameter": [[22, 2, 1, "", "datatype"], [22, 2, 1, "", "sample"]], "domainlab.utils.hyperparameter_sampling.Hyperparameter": [[22, 2, 1, "", "datatype"], [22, 2, 1, "", "get_val"], [22, 2, 1, "", "sample"]], "domainlab.utils.hyperparameter_sampling.ReferenceHyperparameter": [[22, 2, 1, "", "datatype"], [22, 2, 1, "", "sample"]], "domainlab.utils.hyperparameter_sampling.SampledHyperparameter": [[22, 2, 1, "", "datatype"], [22, 2, 1, "", "sample"]], "domainlab.utils.override_interface": [[22, 5, 1, "", "override_interface"]], "domainlab.utils.perf": [[22, 1, 1, "", "PerfClassif"]], "domainlab.utils.perf.PerfClassif": [[22, 2, 1, "", "cal_acc"], [22, 2, 1, "", "gen_fun_acc"]], "domainlab.utils.perf_metrics": [[22, 1, 1, "", "PerfMetricClassif"]], "domainlab.utils.perf_metrics.PerfMetricClassif": [[22, 2, 1, "", "cal_metrics"]], "domainlab.utils.test_img": [[22, 5, 1, "", "mk_img"], [22, 5, 1, "", "mk_rand_label_onehot"], [22, 5, 1, "", "mk_rand_xyd"]], "domainlab.utils.u_import": [[22, 5, 1, "", "import_path"]], "domainlab.utils.u_import_net_module": [[22, 5, 1, "", "build_external_obj_net_module_feat_extract"]], "domainlab.utils.utils_class": [[22, 5, 1, "", "store_args"]], "domainlab.utils.utils_classif": [[22, 5, 1, "", "get_label_na"], [22, 5, 1, "", "logit2preds_vpic"], [22, 5, 1, "", "mk_dummy_label_list_str"]], "domainlab.utils.utils_cuda": [[22, 5, 1, "", "get_device"]], "domainlab.utils.utils_img_sav": [[22, 5, 1, "", "mk_fun_sav_img"], [22, 5, 1, "", "sav_add_title"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:attribute", "4": "py:property", "5": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "property", "Python property"], "5": ["py", "function", "Python function"]}, "titleterms": {"hduva": [0, 2, 6], "hierarch": 0, "variat": [0, 5], "auto": 0, "encod": [0, 6], "FOR": 0, "unsupervis": [0, 6], "domain": [0, 5, 6, 7, 25], "gener": [0, 6, 7, 25], "model": [0, 2, 6, 7, 20], "overview": [0, 2], "evid": 0, "lower": 0, "bound": 0, "overal": 0, "loss": 0, "hyperparamet": [0, 3], "function": 0, "paramet": 0, "warmup": 0, "jigen": [1, 2, 6], "implement": [2, 6, 7], "algorithm": [2, 4, 6, 7], "deepal": [2, 4, 6], "matchdg": [2, 4, 6], "diva": [2, 5, 6], "dann": [2, 6], "trainer": [2, 15], "dial": 2, "benchmark": 3, "domainlab": [3, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], "set": 3, "up": 3, "configur": 3, "sampl": 3, "run": 3, "obtain": 3, "result": [3, 25], "custom": [4, 6, 7, 25], "neural": [4, 6, 25], "network": [4, 6, 25], "exampl": [4, 6], "invari": 5, "autoencod": 5, "color": 6, "version": 6, "mnist": 6, "leav": 6, "one": 6, "out": 6, "choos": 6, "train": 6, "test": 6, "make": 6, "saniti": 6, "check": 6, "dataset": 6, "us": 6, "8": 6, "instanc": 6, "from": 6, "each": 6, "class": 6, "imag": 6, "2": 6, "so": 6, "work": 6, "also": 6, "singl": 6, "larger": 6, "alex": 6, "net": 6, "sandwich": 6, "topic": 6, "classif": 6, "user": 6, "defin": [6, 25], "task": [6, 9, 21, 25], "folder": 6, "extern": [6, 7], "imagepath": 6, "python": 6, "file": 6, "adversari": 6, "extend": [7, 25], "contribut": [7, 25], "extens": 7, "your": [7, 25], "intern": 7, "more": 7, "advanc": 7, "design": [7, 25], "output": [8, 25], "structur": [8, 25], "specif": 9, "taskpathlist": 9, "taskfold": 9, "data": 9, "organ": 9, "specifi": 9, "api": 9, "packag": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25], "subpackag": [10, 11, 16], "submodul": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "arg_pars": 10, "modul": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "content": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], "algo": [11, 12, 13, 14, 15], "a_algo_build": 11, "builder_custom": 11, "builder_dann": 11, "builder_deepal": 11, "builder_di": 11, "builder_diva": 11, "builder_hduva": 11, "builder_jigen1": 11, "builder_matchdg": 11, "zoo_algo": 11, "compo": [12, 16, 17], "matchdg_arg": 12, "matchdg_bas": 12, "matchdg_ctr_erm": 12, "matchdg_match": 12, "matchdg_util": 12, "msel": 13, "a_model_sel": 13, "c_msel": 13, "c_msel_oracl": 13, "observ": 14, "a_observ": 14, "b_obvisitor": 14, "c_obvisitor_cleanup": 14, "c_obvisitor_gen": 14, "a_train": 15, "args_dial": 15, "train_bas": 15, "train_dial": 15, "train_matchdg": 15, "train_visitor": 15, "a_nn_build": 16, "builder_nn_alex": 16, "builder_nn_conv_bn_relu_2": 16, "builder_nn_external_from_fil": 16, "utils_conv_get_flat_dim": 16, "zoo_nn": 16, "nn_zoo": 17, "net_adversari": 17, "net_classif": 17, "net_conv_conv_bn_pool_2": 17, "net_gat": 17, "nn": 17, "nn_alex": 17, "nn_torchvis": 17, "dset": 18, "a_dset_mnist_color_rgb_solo": 18, "dset_img_path_list": 18, "dset_mnist_color_solo_default": 18, "dset_poly_domains_mnist_color_default": 18, "dset_subfold": 18, "utils_color_palett": 18, "utils_data": 18, "utils_wrapdset_patch": 18, "exp_protocol": 19, "run_experi": 19, "a_model": 20, "a_model_classif": 20, "args_jigen": 20, "args_va": 20, "model_custom": 20, "model_dann": 20, "model_deep_al": 20, "model_diva": 20, "model_hduva": 20, "model_jigen": 20, "model_vae_xyd_classif": 20, "wrapper_matchdg": 20, "a_task_classif": 21, "b_task": 21, "task_fold": 21, "task_folder_mk": 21, "task_mnist_color": 21, "task_pathlist": 21, "task_util": 21, "utils_task": 21, "utils_task_dset": 21, "zoo_task": 21, "util": 22, "flows_gen_img_model": 22, "generate_benchmark_plot": 22, "get_git_tag": 22, "hyperparameter_sampl": 22, "override_interfac": 22, "perf": 22, "perf_metr": 22, "test_img": 22, "u_import": 22, "u_import_net_modul": 22, "utils_class": 22, "utils_classif": 22, "utils_cuda": 22, "utils_img_sav": 22, "welcom": 23, "s": 23, "document": 23, "indic": 23, "tabl": 23, "introduct": 25, "playground": 25, "why": 25, "dedic": 25, "get": 25, "start": 25, "instal": 25, "basic": 25, "usag": 25, "storag": 25, "perform": 25, "measur": 25, "softwar": 25, "pattern": 25, "credit": 25, "recommonmark": 26, "0": 26, "5": 26, "dev0": 26}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx.ext.todo": 2, "nbsphinx": 4, "sphinx": 56}}) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index ec92f7600..ea547e0d7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,18 +15,16 @@ # Incase the project was not installed import os import sys -import sphinx_material from datetime import datetime +import sphinx_material + sys.path.insert(0, os.path.abspath("..")) # -- Project information ----------------------------------------------------- project = "domainlab" # @FIXME -copyright = ( - f"2021-{datetime.now().year}, Marr Lab." - "" -) +copyright = f"2021-{datetime.now().year}, Marr Lab." "" author = "Xudong Sun, et.al." @@ -94,11 +92,11 @@ # '.md': 'recommonmark.parser.CommonMarkParser', # } -source_suffix = ['.rst', '.md'] +source_suffix = [".rst", ".md"] source_suffix = { - '.rst': 'restructuredtext', - '.txt': 'markdown', - '.md': 'markdown', + ".rst": "restructuredtext", + ".txt": "markdown", + ".md": "markdown", } # The master toctree document. @@ -114,11 +112,13 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path . -exclude_patterns = ["setup.py", - "_build", - "Thumbs.db", - ".DS_Store", - "**.ipynb_checkpoints"] +exclude_patterns = [ + "setup.py", + "_build", + "Thumbs.db", + ".DS_Store", + "**.ipynb_checkpoints", +] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "default" @@ -129,10 +129,9 @@ # -- HTML theme settings ------------------------------------------------ html_short_title = "domainlab" # @FIXME html_show_sourcelink = False -html_sidebars = {"**": ["logo-text.html", - "globaltoc.html", - "localtoc.html", - "searchbox.html"]} +html_sidebars = { + "**": ["logo-text.html", "globaltoc.html", "localtoc.html", "searchbox.html"] +} html_theme_path = sphinx_material.html_theme_path() html_context = sphinx_material.get_html_context() @@ -157,30 +156,30 @@ "master_doc": False, "nav_title": "DomainLab", "nav_links": [ - { - "href": "readme_link", - "internal": True, - "title": "Introduction"}, - { - "href": "doc_tasks", - "internal": True, - "title": "Task Specification"}, + {"href": "readme_link", "internal": True, "title": "Introduction"}, + {"href": "doc_tasks", "internal": True, "title": "Task Specification"}, { "href": "doc_custom_nn", "internal": True, - "title": "Custom Neural Network"}, + "title": "Specify neural network in commandline", + }, { - "href": "doc_examples", + "href": "doc_MNIST_classification", "internal": True, - "title": "Examples"}, + "title": "Examples with MNIST", + }, { - "href": "doc_output", + "href": "doc_examples", "internal": True, - "title": "Output Structure"}, + "title": "More commandline examples", + }, + {"href": "doc_benchmark", "internal": True, "title": "Benchmarks tutorial"}, + {"href": "doc_output", "internal": True, "title": "Output Structure"}, { "href": "doc_extend_contribute", "internal": True, - "title": "Extend and Contribute"}, + "title": "Developers note", + }, # { # "href": "https://squidfunk.github.io/mkdocs-material/", # "internal": False, @@ -188,7 +187,7 @@ # }, ], "heroes": { - "index": "A pytorch platform for domain generalization", + "index": "DomainLab for modular domain generalization in deep learning", "customization": "Configuration options to personalize your site.", }, "version_dropdown": False, @@ -241,7 +240,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "domainlab", "domainlab", [author], 1)] # @FIXME +man_pages = [(master_doc, "domainlab", "domainlab", [author], 1)] # @FIXME # -- Options for Texinfo output ---------------------------------------------- @@ -256,7 +255,7 @@ "DomainLab Documentation", author, "domainlab", - "A pytorch platform for domain generalization", + "A pytorch platform of modular domain generalization for deep learning", "Miscellaneous", ), ] diff --git a/docs/conf0.py b/docs/conf0.py index 21f1ad1ce..c6138b9f6 100644 --- a/docs/conf0.py +++ b/docs/conf0.py @@ -12,17 +12,18 @@ # import os import sys -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) sys.setrecursionlimit(1500) # -- Project information ----------------------------------------------------- -project = 'domainlab' -copyright = '2022, Xudong Sun' -author = 'Xudong Sun' +project = "domainlab" +copyright = "2022, Xudong Sun" +author = "Xudong Sun" # The full version, including alpha/beta/rc tags -release = '0.0.0' +release = "0.0.0" # -- General configuration --------------------------------------------------- @@ -46,7 +47,7 @@ ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -59,7 +60,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- @@ -67,9 +68,9 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] diff --git a/docs/docDIAL.md b/docs/docDIAL.md new file mode 100644 index 000000000..8b8111de8 --- /dev/null +++ b/docs/docDIAL.md @@ -0,0 +1,74 @@ +# Trainer DIAL +## Domain Invariant Adversarial Learning + +The algorithm introduced in https://arxiv.org/pdf/2104.00322.pdf uses adversarial learning to tackle the task of domain generalization. Therefore, the source domain is the natural dataset, while the target domain is generated using adversarial attack on the source domain. + + +## generating the adversarial domain + +The generation of adversary images is demonstrated in figure 1. +The task is to find an adversary image $x'$ to the natural image $x$ with $||x- x'||$ small, such that the output of a classification network $\phi$ fulfills $||\phi(x) - \phi(x')||$ big. In the example in figure 1 you can for example see, that the difference between the left and the right image of the panda is unobservable, but the classifier does still classify them differently. + +In Domainlab the adversary images are created starting from a random perturbation of the natural image $x'_0 = x + \sigma \tilde{x}~$, $\tilde{x} \sim \mathcal{N}(0, 1)$ and using $n$ steps in a gradient descend with step size $\tau$ to maximize $||\phi(x) - \phi(x')||$. In general machine learning, the generation of adversary images is used during the training process to make networks more robust to adversarial attacks. + +
+ +
Figure 1: adversarial domain (Image source: Figure 1 of Explaining and Harnessing Adversarial Examples https://arxiv.org/abs/1412.6572)
+
+ +## network structure + +The network consists of three parts. At first a feature extractor, which extracts the main characteristics of the images. This features are then used as the input to a label classifier and a domain classifier. +During training the network is optimized to a have low error on the classification task, while ensuring that the internal representation (output of the feature extractor) cannot discriminate between the natural and adversarial domain. This goal can be archived by using a special loss function in combination with a gradient reversal layer. + +
+ +
Figure 2: network structure (Image source: Figure 1 of Domain Invariant Adversarial Learning https://arxiv.org/pdf/2104.00322.pdf)
+
+ + +[comment]: <> (## loss function and gradient reversal layer) + +[comment]: <> (The loss function of the algorithm is a combination of three terms:) + + +[comment]: <> (standard cross entropy loss between the predicted label probabilities and the actual label $CE_{nat}$ for the natural domain, $CE_{adv}$ for the adversarial domain) + +[comment]: <> (Kullback-Leibler divergence between classifier output on the natural images and their adversarial counterparts $KL$) + +[comment]: <> (standard cross-entropy loss between predicted domain probability and domain label $D_{nat}$ for the natural domain, $D_{adv}$ for the adversarial domain) + +[comment]: <> (The loss functions are given by:) + + +[comment]: <> ($$) +[comment]: <> (DIAL_{CE} = CE_{nat} + \lambda ~ CE_{adv} - r / D_{nat} + D_{adv} / ) + +[comment]: <> ($$) + +[comment]: <> ($$) +[comment]: <> (DIAL_{KL} = CE_{nat} + \lambda ~ KL - r / D_{nat} + D_{adv} / ) +[comment]: <> ($$) + + +[comment]: <> (The task is to minimize the label classification loss while maximizing the classification loss for the adversarial domain. Therefore a gradient reversal layer is inserted into the network, right in front of the domain classifier. The layer leaves the input unchanged during forward propagation and reverses the gradient by multiplying it with a negative scalar during the back-propagation. This ensures that the weights in the feature extractor are actually chosen such that they maximize the domain classification loss. The parameter of the gradient reversal layer is initialized to a small value and is then gradually increased to $r$.) + +## loss function and gradient reversal layer + +The loss function for in the DomainLab package is different to the one described in the paper. It consists of the standard cross entropy loss between the predicted label probabilities and the actual label for the natural domain ($CE_{nat}$) and for the adversarial domain ($CE_{adv}$). +The adversarial domain is weighted by the parameter $\gamma_\text{reg}$. + +$$ +\text{loss} = CE_{nat} + \gamma_\text{reg}\,CE_{adv} +$$ + + +--- + +This procedure yields to the following availability of hyperparameter: +- `--dial_steps_perturb`: how many gradient step to go to find an adversarial image ($n$ from "*generating the adversarial domain*") +- `--dial_noise_scale`: variance of gaussian noise to inject on pure image ($\sigma$ from "*generating the adversarial domain*") +- `--dial_lr`: learning rate to generate adversarial images ($\tau$ from "*generating the adversarial domain*") +- `--dial_epsilon`: pixel wise threshold to perturb images +- `--gamma_reg`: ? ($\epsilon$ in the paper) +- `--lr`: learning rate ($\alpha$ in the paper) diff --git a/docs/docFishr.md b/docs/docFishr.md new file mode 100644 index 000000000..08580d9fe --- /dev/null +++ b/docs/docFishr.md @@ -0,0 +1,81 @@ +# Trainer Fishr +## Invariant Gradient Variances for Out-of-distribution Generalization + +The goal of the Fishr regularization technique is locally aligning the domain-level loss landscapes +around the final weights, finding a minimizer around which the inconsistencies between +the domain-level loss landscapes are as small as possible. +This is done by considering second order terms during training, matching +the variances between the domain-level gradients. + +
+ +
Figure 1: Fishr matches the domain-level gradient variances of the +distributions across the training domains (Image source: Figure 1 of "Fishr: +Invariant gradient variances for out-of-distribution generalization")
+
+ + + +### Quantifying inconsistency between domains +Intuitively, two domains are locally inconsistent around a minimizer, if a small +perturbation of the minimizer highly affects its optimality in one domain, but only +minimally affects its optimality in the other domain. Under certain assumptions, most importantly +the Hessians being positive definite, it is possible to measure the inconsistency between two domains +$A$ and $B$ with the following inconsistency score: + +$$ +\mathcal{I}^\epsilon ( \theta^* ) = \text{max}_ {(A,B)\in\mathcal{E}^2} \biggl( \mathcal{R}_ B (\theta^* ) - \mathcal{R}_ {A} ( \theta^* ) + \text{max}_ {\frac{1}{2} \theta^T H_A \theta\leq\epsilon}\frac{1}{2}\theta^T H_B \theta \biggl) +$$ + +, whereby $\theta^*$ denotes the minimizer, $\mathcal{E}$ denotes the set of training domains, +$H_e$ denotes the Hessian for $e\in\mathcal{E}$, $\theta$ denote the network parameters +and $\mathcal{R}_e$ for $e\in\mathcal{E}$ denotes the domain-level ERM objective. +The Fishr regularization method forces both terms on the right hand side +of the inconsistency score to become small. The first term represents the difference +between the domain-level risks and is implicitly forced to be small by applying +the Fishr regularization. For the second term it suffices to align diagonal approximations of the +domain-level Hessians, matching the variances across domains. + + + + +### Matching the Variances during training +Let $\mathcal{E}$ be the space of all training domains, and let $\mathcal{R}_e(\theta)$ be the ERM +objective. Fishr minimizes the following objective function during training: + +$$ +\mathcal{L} (\theta) = \frac{1}{|\mathcal{E}|} \sum_{e\in\mathcal{E}} \mathcal{R}_ {\mathcal{E}} (\theta) + \lambda \mathcal{L}_{\text{Fishr}}(\theta) +$$ + +, whereby + +$$ +\mathcal{L}_ {\text{Fishr}} (\theta) = \frac{1}{|\mathcal{E}|}\sum_{e\in\mathcal{E}} \| v_e -v \|^2_2 +$$ + +with $v_e$ denoting the variance between the gradients of domain $e\in\mathcal{E}$ and +$v$ denoting the average variance of the gradients across all domains, i.e. +$v = \frac{1}{|\mathcal{E}|}\sum_{e\in\mathcal{E}} v_e$. + + + + + +### Implementation +The variance of the gradients within each domain can be computed with the +BACKPACK package (see: Dangel, Felix, Frederik Kunstner, and Philipp Hennig. +"Backpack: Packing more into backprop." https://arxiv.org/abs/1912.10985). +Further on, we use $ \textnormal{Var}(G) \approx \textnormal{diag}(H) $. +The Hessian is then approximated by the Fisher Information Matrix, which +again is approximated by an empirical estimator for computational efficiency. +For more details, see the reference below or the domainlab code. + + + + + + +_Reference:_ +Rame, Alexandre, Corentin Dancette, and Matthieu Cord. "Fishr: +Invariant gradient variances for out-of-distribution generalization." +International Conference on Machine Learning. PMLR, 2022. diff --git a/docs/docHDUVA.md b/docs/docHDUVA.md index edb680595..4abcb71e9 100644 --- a/docs/docHDUVA.md +++ b/docs/docHDUVA.md @@ -1,25 +1,24 @@ -# HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION +# Model HDUVA +## HDUVA: HIERARCHICAL VARIATIONAL AUTO-ENCODING FOR UNSUPERVISED DOMAIN GENERALIZATION -HDUVA builds on a generative approach within the framework of variational autoencoders to facilitate generalization to new domains without supervision. HDUVA learns representations that disentangle domain-specific information from class-label specific information even in complex settings where domain structure is not observed during training. +HDUVA builds on a generative approach within the framework of variational autoencoders to facilitate generalization to new domains without supervision. HDUVA learns representations that disentangle domain-specific information from class-label specific information even in complex settings where domain structure is not observed during training. ## Model Overview -More specifically, HDUVA is based on three latent variables that are used to model distinct sources of variation and are denoted as $z_y$, $z_d$ and $z_x$. $z_y$ represents class specific information, $z_d$ represents domain specific information and $z_x$ models residual variance of the input. We introduce an additional hierarchical level and use a continuous latent representation s to model (potentially unobserved) domain structure. This means that we can encourage disentanglement of the latent variables through conditional priors without the need of conditioning on a one-hot-encoded, observed domain label. The model along with its parameters and hyperparameters is shown in Figure 1: +More specifically, HDUVA is based on three latent variables that are used to model distinct sources of variation and are denoted as $z_y$, $z_d$ and $z_x$. $z_y$ represents class specific information, $z_d$ represents domain specific information and $z_x$ models residual variance of the input. We introduce an additional hierarchical level and use a continuous latent representation s to model (potentially unobserved) domain structure. This means that we can encourage disentanglement of the latent variables through conditional priors without the need of conditioning on a one-hot-encoded, observed domain label. The model along with its parameters and hyperparameters is shown in Figure 1:
- PGM for HDUVA + PGM for HDUVA
Figure 1: Probabilistic graphical model for HDUVA:Hierarchical Domain Unsupervised Variational Autoencoding.
- - Note that as part of the model a latent representation of $X$ is concatentated with $s$ and $z_d$ (dashed arrows), requiring respecive encoder networks. ## Evidence lower bound and overall loss -The ELBO of the model can be decomposed into 4 different terms: +The ELBO of the model can be decomposed into 4 different terms: -Likelihood: $E_{q(z_d, s|x), q(z_x|x), q(z_y|x)}\log p_{\theta}(x|s, z_d, z_x, z_y)$ +Likelihood: $E_{q(z_d, s|x), q(z_x|x), q(z_y|x)}\log p_{\theta}(x|s, z_d, z_x, z_y)$ -KL divergence weighted as in the Beta-VAE: $-\beta_x KL(q_{\phi_x}(z_x|x)||p_{\theta_x}(z_x)) - \beta_y KL(q_{\phi_y}(z_y|x)||p_{\theta_y}(z_y|y))$ +KL divergence weighted as in the Beta-VAE: $-\beta_x KL(q_{\phi_x}(z_x|x)||p_{\theta_x}(z_x)) - \beta_y KL(q_{\phi_y}(z_y|x)||p_{\theta_y}(z_y|y))$ Hierarchical KL loss (domain term): $- \beta_d E_{q_{\phi_s}(s|x), q_{\phi_d}(z_d|x, s)} \log \frac{q_{\phi_d}(z_d|x, s)}{p_{\theta_d}(z_d|s)}$ @@ -29,30 +28,30 @@ In addition, we construct the overall loss by adding an auxiliary classsifier, b ## Hyperparameters loss function -For fitting the model, we need to specify the 4 $\beta$-weights related to the the different terms of the ELBO ( $\beta_x$ , $\beta_y$, $\beta_d$, $\beta_t$) as well as $\gamma_y$. +For fitting the model, we need to specify the 4 $\beta$-weights related to the the different terms of the ELBO ( $\beta_x$ , $\beta_y$, $\beta_d$, $\beta_t$) as well as $\gamma_y$. -## Model parameters -In addition to these hyperparameters, the following model parameters can be specified: +## Model hyperparameters +In addition to these hyperparameters, the following model parameters can be specified: -- Size of latent space for domain-specific information: zd_dim -- Size of latent space for residual variance: zx_dim -- Size of latent space for class-specific information: zy_dim -- Size of latent space for topics $s$: topic_dim -- Size of latent space for latent image representation for topic: topic_h_dim -- Size of latent space for latent image representation for domain: img_h_dim +- `zd_dim`: size of latent space for domain-specific information +- `zx_dim`: size of latent space for residual variance +- `zy_dim`: size of latent space for class-specific information +- `topic_dim`: size of dirichlet distribution for topics $s$ -Finally, 2 models need to be specified: A network converting an image to a topic distribution (of size topic_h_dim) and an encoder converting an image to a latent representation that can be concatenated to $z_d$ (size img_h_dim). The names and paths of the networks are: +The user need to specify at least two neural networks for the **encoder** part via -- nname_topic_distrib_img2topic -- npath_topic_distrib_img2topic +- `npath_encoder_x2topic_h`: the python file path of a neural network that maps the image (or other +modal of data to a one dimensional (`topic_dim`) hidden representation serving as input to Dirichlet encoder: `X->h_t(X)->alpha(h_t(X))` where `alpha` is the neural network to map a 1-d hidden layer to dirichlet concentration parameter. -and -- nname_encoder_sandwich_layer_img2h4zd -- npath_encoder_sandwich_layer_img2h4zd +- `npath_encoder_sandwich_x2h4zd`: the python file path of a neural network that maps the +image to a hidden representation (same size as `topic_dim`), which will be used to infere the posterior distribution of `z_d`: `topic(X), X -> [topic(X), h_d(X)] -> zd_mean, zd_scale` +Alternatively, one could use an existing neural network in DomainLab using `nname` instead of `npath`: +- `nname_encoder_x2topic_h` +- `nname_encoder_sandwich_x2h4zd` -## Hyperparameter warmup -Finally, the number of epochs for hyper-parameter warm-up can be specified via the argument warmup +## Hyperparameter for warmup +Finally, the number of epochs for hyper-parameter warm-up can be specified via the argument `warmup`. Please cite our paper if you find it useful! ```text diff --git a/docs/docJiGen.md b/docs/docJiGen.md index a26331b04..dc67c3c02 100644 --- a/docs/docJiGen.md +++ b/docs/docJiGen.md @@ -1,14 +1,38 @@ -# JiGen +# Model JiGen -The JiGen method proposed in [https://arxiv.org/abs/2007.01434](https://arxiv.org/abs/1903.06864) by Carlucci et al. extends the understanding of the concept of spatial correlation in the neuronal network by training the network not only on a classification task, but also on solving jigsaw puzzles. +
+
+ +
+
-For the jigsaw puzzles the images are split into $n \times n$ patches and permutated. -The model is to predict the permutation index which result in the permutated image. +The JiGen method extends the understanding of the concept of spatial correlation in the +neural network by training the network not only on a classification task, but also on solving jigsaw puzzles. -To be able to solve the classification problem and the jigsaw puzzle in parallel, shuffled and ordered images will first be fed into a convolutional network for feature extraction and will then be given to the image classifier and the jigsaw classifier. +To create a jigsaw puzzle, an image is split into $n \times n$ patches, which are then permuted. +The goal is training the model to predict the correct permutation, which results in the permuted image. -For the training of classificaiton task the network uses a cross-entropy loss for both tasks while weighting the jigsaw classifier by a hyper parameter. Additionally the relative ratio or probability of shuffling the tiles of one instance from training data set is given by another hyper parameter. +To solve the classification problem and the jigsaw puzzle in parallel, the permuted and +the original images are first fed into a convolutional network for feature extraction and then given +to two classifiers, one being the image classifier and the other the jigsaw classifier. -The advantage of this method is that is does not require domain label, as the jigsaw puzzle can be solved despite the missing domain labels. +For the training of both classification networks, a cross-entropy loss is used. The total loss is then +given by the loss of the image classification task plus the loss of the jigsaw task, whereby the +jigsaw loss is weighted by a hyperparameter. +Another hyperparameter denotes the probability of shuffling the patches of one instance from the training +data set, i.e. the relative ratio. +The advantage of this method is that it does not require domain labels, as the jigsaw puzzle can be +solved despite missing domain labels. + +### Model parameters +The following hyperparameters can be specified: +- `nperm`: number of patches in a permutation +- `pperm`: relative ratio, as explained above +- `gamma_reg`: weighting term for the jigsaw classifier + +Furthermore, the user can specify a custom grid length via `grid_len`. + +_Reference_: Carlucci, Fabio M., et al. "Domain generalization by solving jigsaw puzzles." +Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019. diff --git a/docs/docMatchDG.md b/docs/docMatchDG.md new file mode 100644 index 000000000..96eea99f1 --- /dev/null +++ b/docs/docMatchDG.md @@ -0,0 +1,71 @@ +# Trainer MatchDG +## Domain Generalization using Causal Matching + +This algorithm introduced in https://arxiv.org/pdf/2006.07500.pdf is motivated by causality theory. The authors try to enforce, that a model does classify an image only on the object information included in the image and not on the domain information. + +## Motivation: causality theory + +The authors of the paper motivate their approach by looking at the data-generation process. The underlying causal model (SCM) is given in figure 1. In the graphic one starts of from the object $O$ and the domain D. The object is directly influenced by its true label $y_\text{true}$ while label and domain do only correlate with each other. Additionally the object is correlated with the domain conditioned on $y_\text{true}$. The information from the object $O$ and the domain $D$ do together form the image $x$ which shall be classified by the neuronal network. Doing so, the object does contribute to the image by providing high-level causal features $x_C$ that are common to any image of the same object. This features are the key for classifying the object, as there is only subliminal influence of the domain, therefore the prediction $y$ is only depending on this causal features. The second contribution to the image are domain-dependent high-level features of the object $x_A$, which depend on both, the object $O$ and the domain $D$. This domain-dependent features shall not be respected in the classification as there is a high influence of the domain. + + +
+ +
Figure 1: Structural causal model for the data-generating process. Observed variables are shaded; dashed arrows denote correlated nodes. Object may not be observed. (Image source: Figure 2 of Domain Generalization using Causal Matching https://arxiv.org/pdf/2006.07500.pdf)
+
+ + +## Network + +Before defining the network, one needs to define three sets: +- $\mathcal{X}$: image space with $x \in \mathcal{X}$ +- $\mathcal{C}$: causal feature space with $x_C \in \mathcal{C}$ +- $\mathcal{Y}$: label space with $y \in \mathcal{Y}$ + +For the classification the goal is to classify an object only based on its causal features $x_C$, hence we define a network $h: \mathcal{C} \rightarrow \mathcal{Y}$. Since $x_C$ for an image $x$ is unknown, one needs to learn a representation function $\phi: \mathcal{X} \rightarrow \mathcal{C}$. By assumption for two images $x_j^{(d)}$ and $x_k^{(d')}$ of the same class, but from different domains $\text{ dist}\left(\phi(x_j^{(d)}), \phi(x_k^{(d')})\right)$ is small to enforce that the features in $\phi(x) \in \mathcal{C}$ are affected by the associated object and not the domain. This motivates the definition of a match function $\Omega: \mathcal{X} \times \mathcal{X} \rightarrow \{0, 1\}$, + +$$ +\Omega(x_j, x_k) = \begin{cases} +1 \quad & \text{$x_j$ and $x_k$ correspond to the same object} \\ +0 & \text{otherwise} +\end{cases} +$$ + +by using + +$$ +\sum_{\substack{\Omega(x_j, x_k) = 1,\\ d \neq d'}} \text{dist}\left(\phi(x_j^{(d)}), \phi(x_k^{(d')})\right) = 0. +$$ + +Together the networks form the desired classifier $f = h \circ \phi : \mathcal{X} \rightarrow \mathcal{Y}$. + + +## Training + +**Initialisation:** first of all match pairs of same-class data points from different domains are constructed. Given a data point, another data point with the same label from a different domain is selected randomly. The matching across domains is done relative to a base domain, which is chosen as the domain with the highest number of samples for that class. This leads to a matched data matrix $\mathcal{M}$ of size $(N', K)$ with $N'$ sum of the size of base domains over all classes and $K$ number ob domains. + +**Phase 1:** sample batches $(B, K)$ from $\mathcal{M}$, with $B$ is batch size and train a match function $\Omega: \mathcal{X} \times \mathcal{X} \rightarrow \{0, 1\}$, by adapting the network parameter in $\phi$ to minimize the contrastive loss for every positive match pair $(x_j, x_k)$ + +$$ +l(x_j, x_k) = -\log\left(\frac{ \exp\left( \frac{\text{sim}(j, k)}{\tau} \right) }{ \exp\left( \frac{\text{sim}(j, k)}{\tau} \right) + \sum\limits_{\substack{i=0,\\ y_i \neq y_j}} \exp\left( \frac{\text{sim}(j, i)}{\tau} \right) }\right) +$$ + +where $\text{sim}(a, b) = \frac{\phi(x_a)^T \phi(x_b)}{||\phi(x_a)||~||\phi(x_b)||}$ is the cosine similarity and $\tau$ is a hyperparameter (`--tau`). + +After $t$ epochs (`--epos_per_match_update`) the match tensor is updated. The same procedure of selecting a base domain for each class is used, but instead of randomly matching data points across domains, we find the nearest neighbor among the data point in base domain and data points in the other domains, having the same class label, with respect to $l_2$ distance between their representations $\phi_\text{epoch}(x)$. + + +**Phase 2:** Finally the classifier $f = h \circ \phi$ is trained using + +$$ +\underset{h, \phi}{\text{arg min}} ~ \sum_{d \in D} \sum_{i=1}^{n_d} ~ l\left(h(\phi(x_i^{(d)})), y_i^{(d)}\right) + \gamma_{\text{reg}} \sum_{\substack{\Omega(x_j, x_k) = 1,\\ d \neq d'}} \text{dist}\left(\phi(x_j^{(d)}), \phi(x_k^{(d')})\right). +$$ + +The training of $h$ and $\phi$ is performed from scratch. The trained network $\phi^*$ from phase 1 is only used to update the matched data matrix using yielding $\Omega$. + +--- + +This procedure yields to the following availability of hyperparameter: +- `--tau`: hyperparameter in the contrastive loss. In the paper this parameter is chosen to be $0.05$ in all experiments. ($\tau$ from phase 1) +- `--epochs_ctr`: number of epochs for minimizing the contrastive loss in phase 1. +- `--epos_per_match_update`: Number of epochs before updating the match tensor. ($t$ from phase 1) +- `--gamma_reg`: weight for the regularization term in phase 2. ($\gamma_\text{reg}$ from phase 2) diff --git a/docs/doc_MNIST_classification.md b/docs/doc_MNIST_classification.md new file mode 100644 index 000000000..a979b66f3 --- /dev/null +++ b/docs/doc_MNIST_classification.md @@ -0,0 +1,95 @@ +# colored MNIST classification + +We include in the DomainLab package colored verion of MNIST where the color corresponds to the domain and digit corresponds to the semantic concept that we want to classify. + +## colored MNIST dataset +We provide 10 different colored version of the MNIST dataset with numbers 0 to 9 as 10 different domains. The digit and background are colored differently, thus a domain correspond to a 2-color combination. +An extraction of digit 0 to 9 from domain 0 is shown in Figure 1. + +
+digits 0 - 9: + + + + + + + + + +
Figure 1: digits zero to nine from domain zero of colored MNIST
+
+ +
+The available digit-background color combinations together with the domain number are shown in Figure 2. For simplicity we only show examples of the digit 0. +Note that for domain 0 we have red in the background and blue for the digit. This exact same colors are also used in domain 3 but reversed with blue in the background and red for the digit. The same can also be seen for the other domains, which also come in pairs. +
+ +
+ domain 0:
+ domain 1:
+ domain 2:
+ domain 3:
+ domain 4:
+ domain 5:
+ domain 6:
+ domain 7:
+ domain 8:
+ domain 9: +
Figure 2: digit zero from domain zero to nine of colored MNIST
+
+
+ +## domain generalisation on colored MNIST + +A particular hard task for domain generalization is, if only a few training domains are available and the test domain differs a lot from the train domains. Here we use domain 0 and 3, from Figure 2, for the training, while choosing domain 1 and 2 for testing as the colors appearing here are far different from the ones used in training. + +For our test we like to compare diva and erm, this was done using the following command prompts: + +### erm (Emperical Risk Minimization) + +```shell +python main_out.py --te_d 1 2 --tr_d 0 3 --task=mnistcolor10 --epos=500 --bs=16 --model=erm --nname=conv_bn_pool_2 --lr=1e-3 --seed=0 --san_check --san_num=8 +``` + +### diva + +```shell +python main_out.py --te_d 1 2 --tr_d 0 3 --task=mnistcolor10 --epos=500 --bs=16 --model=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --lr=1e-3 --seed=0 --gamma_y=1e5 --gamma_d=1e5 --san_check --san_num=8 +``` + +### Results + +For both algorithms the early stop criterion ended the training. The performance of the trained models on the test domains are summarized in the following table: + +| method | epochs | acc | precision | recall | specificity | f1 | auroc | +| - | - | - | - | - | - | - | - | +| erm | 9 | 0.798 | 0.858 | 0.800 | 0.978 | 0.797 | 0.832 | +| diva | 16 | 0.959 | 0.961 | 0.958 | 0.995 | 0.958 | 0.999 | + + +### Detailed prompt explanation +- `--te_d 1 2` sets the test domain to domain 1 and 2 +- `--tr_d 0 3` sets the train domain to domain 0 and 3 +- `--task=mnistcolor10` points the program to a task description containing all information about how and where to the training and testing data is saved as well as about transformations which should be done before training. More about this can be found in *doc_task.md*. +- `--epos=500` sets the maximal number of epos to 500. This value is set sufficiently high such that the training terminates, by using the early stopping criterion, to ensure full convergence for both algorithms. +- `--bs=16` sets the batch size t0 16 +- `--model=...` specifies the algorithm, in our case `erm` and `diva`. +- `--nname=conv_bn_pool_2` specifies which network structure should be used as an underlying basis for the algorithms. `conv_bn_pool_2` is is already implemented into Domainlab, its structure is given by +``` +nn.Sequential( + nn.Conv2d(in_channels=num_of_input_channels, out_channels=32, kernel_size=5, stride=1, bias=False), + nn.BatchNorm2d(num_features=32), + nn.ReLU(), + nn.MaxPool2d(kernel_size=2, stride=2), + nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, bias=False), + nn.BatchNorm2d(num_features=64), + nn.ReLU(), + nn.MaxPool2d(kernel_size=2, stride=2), +) +``` +- `--nname_dom=conv_bn_pool_2` gives the second neuronal network structure, which is only needed for the diva algorithm +- `--lr=1e-3` sets the learning rate for the training +- `--seed=0` sets a seed for the training +- `--gamma_y==1e5` and `gamma_d=1e5` are hyperparameter of diva +- `--san_check` and `--san_num=8` are only used to generate the dataset extractions plotted in figure 1 & 2 and to check if the datasets we used for training are correct diff --git a/docs/doc_algos.md b/docs/doc_algos.md deleted file mode 100644 index 664f40bfc..000000000 --- a/docs/doc_algos.md +++ /dev/null @@ -1,23 +0,0 @@ -# Overview of implemented models and algorithms - -Note DomainLab decomposes the concept of model from network and algorithm. That is, the model only defines the loss of the neural network, while the architecture of the neural network can be specified independently as a component of the model, and algorithm is model with a specified trainer and observer. Algorithm share the same name as model with a default trainer specified. - -## algorithm "deepall" -Pool all domains together and train an ERM (empirical risk minimization) model - -## algorithm "matchdg" -Mahajan, Divyat, Shruti Tople, and Amit Sharma. "Domain generalization using causal matching." International Conference on Machine Learning. PMLR, 2021. -## algorithm "diva" -Ilse, Maximilian, et al. "Diva: Domain invariant variational autoencoders." Medical Imaging with Deep Learning. PMLR, 2020. - -## algorithm "hduva" -Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization: https://arxiv.org/pdf/2101.09436.pdf, ICLR 2020 RobustML. - -## algorithm "dann": -Ganin, Yaroslav, et al. "Domain-adversarial training of neural networks." The journal of machine learning research 17.1 (2016): 2096-2030. - -## algorithm "jigen": -Carlucci, Fabio M., et al. "Domain generalization by solving jigsaw puzzles." Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019. https://arxiv.org/abs/1903.06864 - -## algorithm deepall, dann, diva with trainer "dial" -Levi, Matan, Idan Attias, and Aryeh Kontorovich. "Domain invariant adversarial learning.", Transactions on Machine Learning Research, arXiv preprint arXiv:2104.00322 (2021). diff --git a/docs/doc_benchmark.md b/docs/doc_benchmark.md index 7006ca05f..082b14632 100644 --- a/docs/doc_benchmark.md +++ b/docs/doc_benchmark.md @@ -1,55 +1,170 @@ # Benchmarking with DomainLab -The package offers the ability to benchmark different algorithms against each other. +[Documentation for Benchmark in Markdown](https://github.com/marrlab/DomainLab/blob/master/docs/doc_benchmark.md) + +The package offers the ability to benchmark different user-defined experiments against each other, +as well as against different hyperparameter settings and random seeds. The results are collected in a csv file, but also prepared in charts. Within each benchmark, two aspects are considered: -1. Stochastic variation: Variation of the performance with respect to different random seeds. -2. Sensitivity to selected hyperparameters: By sampling hyperparameters randomly, -the performance with respect to different hyperparameter choices is investigated. +1. Stochastic variation: variation of the performance with respect to different random seeds. +2. Sensitivity to selected hyperparameters: by sampling hyperparameters randomly, +the performance with respect to different hyperparameter choices is investigated. + +## Dependencies installation + +DomainLab relies on `Snakemake` for its benchmark functionality. + +### Unix installation +snakemake depends on pulp due to an upgrde of pulp, snakemake becomes unstable, so we recommed install the following version. +``` +pip install snakemake==7.32.0 +pip install pulp==2.7.0 +``` + +### Windows installation details + +Benchmarking is currently not tested on Windows due to the dependency on `Snakemake` and `datrie` +One could, however, try install minimal Snakemake via +`mamba create -c bioconda -c conda-forge -n snakemake snakemake-minimal` +to see if the following function still works + ## Setting up a benchmark -The benchmark is configured in a yaml file. We refer to the -[demo_benchmark.yaml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_benchmark.yaml) -for a documented example. As one can see here, the user has to select: -- Common arguments for all tasks. This typically includes the dataset on which the benchmark -shall be performed, as well as the number of epochs and batch size for training. -Here also the number of different random seeds and hyperparameter samples is set. -- The domains which are used as leave-one-out for testing. -- Different tasks, where each task contains: (1) Fixed parameters specific for this task, -typically the algorithm name and related arguments and (2) varying hyperparameters, for which -the sensitivity shall be investigated. - -Set `sampling_seed` for a fully reproducible benchmark. - -## Configure hyperparameter sampling -An example files of the possibilities for hyperparameter sampling is -[demo_hypeparameter_sampling.yml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_hyperparameter_sampling.yml). -This file is of course an extract of [demo_benchmark.yaml](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/yaml/demo_benchmark.yaml), -the sampling for benchmarks is specified directly in this single configuration file. - -In this example we can see: -- Every node containing `aname` is considered as a task -- Hyperparameters can be sampled from different distributions and -- Constraints between the hyperparameters of the same task can be specified. -- By using the `categorical` distribution type, a list of valid values for a hyperparameter can be specified. -- Equality constraints are not supported in the constraints section. To -enforce equality of two hyperparameters use the `reference` key, see `p4` of `Task1`. -References are supported only to sampled hyperparameters, referencing a reference -results in undefined behaviour. - -Note that for sampling, there is always first a sample drawn ignoring the constraints, which -is then possibly rejected by the constraints. If 10,000 samples are rejected in a row, the sampling -aborts with error. +The benchmark is configured in a yaml file. We refer to [doc_benchmark_yaml.md](https://github.com/marrlab/DomainLab/blob/master/docs/doc_benchmark_yaml.md) for a documented +example. ## Running a benchmark -For executing the benchmark, a sample command can be found -[here](https://github.com/marrlab/DomainLab/blob/benchmark_snakemake/examples/benchmark/run_snakemake.sh). -If several cores are provided, the benchmark is parallelized per hyperparameter sample and -task. +For the execution of a benchmark we provide two scripts in our repository: +- local version for running the benchmark on a standalone machine: +[run_benchmark_standalone.sh](https://github.com/marrlab/DomainLab/blob/master/run_benchmark_standalone.sh) +- cluster version for running the benchmark on a slurm cluster: [run_benchmark_slurm.sh](https://github.com/marrlab/DomainLab/blob/master/run_benchmark_slurm.sh) + +### Benchmark on a standalone machine (with or without GPU) +To run the benchmark with a specific configuration on a standalone machine, inside the DomainLab +folder, one can execute (we assume you have a machine with 4 cores or more) +```shell +# Note: this has only been tested on Linux based systems and may not work on Windows +./run_benchmark_standalone.sh ./examples/benchmark/demo_benchmark.yaml 0 0 2 +``` +where the first argument is the benchmark configuration file (mandatory), the second and the third +arguments are the starting seeds for cuda and the hyperparameter sampling (both optional) and the +fourth argument is the number of GPUs to use (optional). The number of GPUs defaults to one +(if your machine does not have GPU, the last argument defaults to one as well and CPU is used). + +In case of snakemake error, try +`rm -r .snakemake/` + +### Benchmark on a HPC cluster with slurm +If you have access to an HPC cluster with slurm support: In a submission node, clone the DomainLab +repository, cd into the repository and execute the following command: + +**Make sure to use tool like nohup or tmux to keep the following command active!** + +It is a good idea to use standalone script to test if the yaml file work or not before submit to slurm cluster. + +```cluster +# Note: this has only been tested on Linux based systems and may not work on Windows +./run_benchmark_slurm.sh ./examples/benchmark/demo_benchmark.yaml +``` +Similar to the local version explained above, the user can also specify a random seed for +hyperparameter sampling and pytorch. + +#### Check errors for slurm runs +The following script will help to find out which job has failed and the error message, so that you could direct to the +specific log file +```cluster +bash ./sh_list_error.sh ./zoutput/slurm_logs +``` +#### Map between slurm job id and sampled hyperparameter index +suppose the slurm job id is 14144163, one could the corresponding log file in `./zoutput/slurm_logs` folder via +`find . | grep -i "14144163"` + +the results can be +`run_experiment-index=41-14144163.err` +where `41` is the hyperparameter index in `zoutput/benchmarks/[name of the benchmark]/hyperparameters.csv`. + ## Obtained results -All files created by this benchmark are saved in the given output directory. -The sampled hyperparameters can be found in `hyperparameters.csv`. -The performance of the different runs can be found in `results.csv`. Moreover, there is -the `graphics` subdirectory, in which the values from `results.csv` are visualized for interpretation. +All files created by this benchmark are saved in the given output directory +(by default `./zoutput/benchmarks/[name of the benchmark defined in YAML file]`). The sampled hyperparameters can be found in +`hyperparameters.csv`. The yaml file is translated to `config.txt` with corresponding to commit in formation in `commit.txt` (**do not update code during benchmark process so results can be reproducible with this commit information**), corresponding to each line in `hyperparameters.csv`, there will +be a csv file in directory `rule_results`. + +#### Output folder structure + +via `tree -L 2` in `zoutput/benchmarks/[name of the benchmark defined in configuration yaml file]`, one can get something like below + +``` +├── commit.txt +├── config.txt +├── graphics +│   ├── diva_fbopt_full +│   ├── radar_dist.png +│   ├── radar.png +│   ├── scatterpl +│   ├── sp_matrix_dist.png +│   ├── sp_matrix_dist_reg.png +│   ├── sp_matrix.png +│   ├── sp_matrix_reg.png +│   └── variational_plots +├── hyperparameters.csv +├── results.csv +└── rule_results + ├── 0.csv + ├── 1.csv + ├── 2.csv + ├── 3.csv + ├── 4.csv + ├── 5.csv + ├── 6.csv + └── 7.csv +``` +where commit.txt contains commit information for reproducibility, config.txt is a json format of the configuration yaml file for reproducibility, graphics folder contains the visualization of benchmark results in various plots, specificly, we use `graphics/variational_plot/acc/stochastic_variation.png`, hyperparameters.csv contains all hyperparameters used for each method, results.csv is an aggregation of the csv files in `rule_results`, where the i.csv correspond to the parameter index in hyperparameters.csv + +**Please do not change anything in folder `rule_results` !** + +The performance of the different runs from directory `rule_results` will be aggregated after all jobs have been done, which can be found aggregated in `results.csv`, Moreover, there is the `graphics` subdirectory, in which the values from `results.csv` are +visualized for interpretation. + +In case that the benchmark is not entirely completed, the user can obtain partial results as +explained below. + + +### Obtain partial results +If the benchmark is not yet completed (still running or has some failed jobs, e.g. BrokenPipe Error due to multiprocessing in PIL image reading), the `results.csv` file containing the aggregated results will not be created. +The user can then obtain the aggregated partial results with plots from the partially completed benchmark by running +the following after cd into the DomainLab directory: +```commandline +python main_out.py --agg_partial_bm OUTPUT_DIR +``` +specifying the benchmark output directory containing the partially completed benchmark, +e.g. `./zoutput/benchmarks/demo_benchmark`, where `demo_benchmark` is a name defined in the yaml file. + +Alternatively, one could use +```examples +cat ./zoutput/benchmarks/[name of the benchmark]/rule_results/*.csv > result.csv +``` +clean up the extra csv head generated and plot the csv using command below + +### Generate plots from .csv file +If the benchmark is not completed, the `graphics` subdirectory might not be created. The user can then manually +create the graphics from the csv file of the aggregated partial results, which can be obtained as explained above. +Here for, the user must cd into the DomainLab directory and run + +```commandline +python main_out.py --gen_plots CSV_FILE --outp_dir OUTPUT_DIR +``` + +specifying the path of the csv file of the aggregated results (e.g. `./zoutput/benchmarks/demo_benchmark/results.csv`) +and the output directory of the partially completed benchmark (e.g. `./zoutput/benchmarks/demo_benchmark`). +Note that the cvs file must have the same form as the one generated by the fully executed benchmark, i.e. + + + + + +| param_index | task | algo | epos | te_d | seed | params | acc | precision | recall | specificity | f1 | auroc | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| 0 | ... | ... | ... | ... | ... | {'param1': p1, ...} | ... | ... | ... | ... | ... | ... | +| 1 | ... | ... | ... | ... | ... | {'param1': p2, ...} | ... | ... | ... | ... | ... | ... | diff --git a/docs/doc_benchmark_further_explanation.md b/docs/doc_benchmark_further_explanation.md new file mode 100644 index 000000000..fdf0048c5 --- /dev/null +++ b/docs/doc_benchmark_further_explanation.md @@ -0,0 +1,89 @@ +## Further explanations to Benchmark Setup +The user can create different custom experiments, which are to be benchmarked. Each +experiment can have a custom name. + +An experiment can specify following arguments: +- `model`: name of the model. An experiment with an incorrect `model` is not considered in the +benchmark (mandatory) +- `hyperparameters`: model-specific hyperparameters (for more details on the hyperparameters we +refer to the model-specific documentation). The hyperparameters can be randomly sampled, see +next section (optional) +- `shared`: a list of parameters, which the respective experiment shares with another experiment +(optional) +- `constraints`: a list of constraints for the hyperparameters, see section below (optional) +- `trainer`: trainer to be used (optional, e.g. "dial" or "mldg") +- model-specific arguments (for more details we refer to the model-specific documentation) + +Furthermore, the user can declare: +- `domainlab_args`: common arguments for all benchmarking experiments, including: + - `tpath`/`task`: path to/name of the task which should be addressed (mandatory) + - `epos`: number of epochs (int, mandatory) + - `bs`: batch size for training (int, mandatory) + - `lr`: learning rate (float, mandatory) + - `es`: early stop steps (int, optional) + - `npath`/`nname`: path to/name of the neural network, which should be used for feature extraction + (mandatory, can also be specified within each experiment) + - `dmem`: `True` or `False` (optional) + - `san_check`: `True`or `False` (optional) + - `te_d`: list of test domains (mandatory) + - `tr_d`: list of training domains (mandatory) +- `output_dir`: path to the custom output directory (mandatory) +- `startseed`: creates reproducible results (mandatory) +- `endseed`: creates reproducible results (mandatory) +- `mode`: set to `grid` to apply grid search for hyperparameter sampling (optional, for details see next section) +- `Shared params`: an optional list including the shared hyperparameters with respective sampling distribution +(mandatory if Shared params should be used) and in case of random sampling `num_shared_param_samples` +(number of samples for the shared hyperparameters, mandatory for random sampling) + +Depending on which hyperparameter sampling technique is used (see section below), the user must also +respect/declare the following: +- random hyperparameter sampling: + - `sampling_seed` (int) must be defined outside the experiments + - `num_param_samples`: number of hyperparameters to be sampled (int, mandatory), must be defined outside the experiments + - `distribution`: specifies the distribution used for sampling, must be specified for each + hyperparameter, for available distributions see section below (mandatory) + - `step`: "step-size" (float) between samples. Only points being a multiple of the step-size apart + can be sampled. `0` means that each real number can be sampled. + - `num_shared_param_samples`: number of samples for the shared hyperparameters. Must be defined + inside the Shared params section (if this section is used) +- grid search hyperparameter sampling (`mode`:`grid`): + - `num`: number of hyperparameters to be sampled (int) must be specified for each hyperparameter + (mandatory) + - `distribution`: specifies the distribution used for sampling, must be specified for each + hyperparameter (for available distributions see section below) + - `step`: "step-size" (float) of the grid points. Only points lying on the grid + can be sampled. `0` means that each real number represents a grid point and thus, can be sampled. + + +### Hyperparameter sampling +The benchmark offers the option to randomly sample hyperparameters from different distributions. +An example can be found in [demo_hyperparameter_sampling.yml](https://github.com/marrlab/DomainLab/blob/master/examples/yaml/demo_hyperparameter_sampling.yml). We offer two sampling +techniques, random hyperparameter sampling and grid search. The default sampling mode is random +hyperparameter sampling. If grid search should be applied, the user must specify `mode`:`grid`. + +Each sampling technique offers the following distributions: +- `categorical` distribution. For each parameter the user can specify: + - `values`: a list of valid values + - `datatype`: the datatype of the list values (int or float, default: float) +- `uniform` and `loguniform` distribution. The user must define the following for each +hyperparameter (mandatory): + - `mean`: mean of normal distribution (float) + - `std`: standard deviation of normal distribution (float $\geq 0$) + - `datatype`: the datatype of the list values (int or float, default: float) +- `normal` and `lognormal`distribution. The user must define the following for each hyperparameter + (mandatory): + - `min`: lower bound for samples (int) + - `max`: upper bound for samples (int) + - `datatype`: the datatype of the list values (int or float, default: float) + + + +### Constraints +The user can specify a list of constraints for the hyperparameters. Please note the following: +- We currently use rejection sampling, to prevent the case of contradictory constraints, +amongst others. In concrete, the sampling aborts with an error if 10.000 samples are rejected in a +row. +- Equality constraints are not supported in the constraints section. To enforce equality of two or +more hyperparameters use the `reference` key, see `p4` of `Task1` in +[demo_hypeparameter_sampling.yml](https://github.com/marrlab/DomainLab/blob/master/examples/yaml/demo_hyperparameter_sampling.yml). References are only supported to reference sampled hyperparameters, e.g. +referencing a reference results in undefined behaviour. diff --git a/docs/doc_benchmark_pacs.md b/docs/doc_benchmark_pacs.md new file mode 100644 index 000000000..630a4d57e --- /dev/null +++ b/docs/doc_benchmark_pacs.md @@ -0,0 +1,4 @@ + +## Let DomainLab know where your PACS data were located +We define the diretory containing PACS data here [relative directory of PACS dataset with respect to the DomainLab repository](https://github.com/marrlab/DomainLab/blob/70ce95c8093ffec0f4b63734d06d2521815a9da7/examples/tasks/task_pacs_path_list.py#L13) +To avoid changing the code, which is always discouraged, one could make a symbolic link of your PACS dataset to the required directory in the code above [see examples here](https://github.com/marrlab/DomainLab/blob/master/sh_pacs.sh) diff --git a/docs/doc_benchmark_yaml.md b/docs/doc_benchmark_yaml.md new file mode 100644 index 000000000..2706080ae --- /dev/null +++ b/docs/doc_benchmark_yaml.md @@ -0,0 +1,300 @@ +# Benchmark yaml files + +yaml files are a powerful tool to specify the details of a benchmark. +The following examples on how a yaml file could look like will lead you through constructing your own yaml file for a benchmark. + +We will start with the general setting of the yaml file and then continue with the description of how to define the sampling/gridsearch for the hyperparameters. + +## General setup of the yaml file + +One may start with a very general setup of the file, defining all fixed information like task description, test and training domains, used algorithms ... + +At the top level, we need to decide whether the random sampling or grid search shall be used. + +For random samples we need to define the total number of hyperparameter samples in each sampling task (`num_param_samples`) and a sampling seed for the hyperparameters (`sampling_seed`). + +For grid search the mode needs to be switched to grid using `mode: grid`, the specification on how many samples sould be created in gridsearch will be done in the next section when setting up the parameter ranges and distributions. + +```yaml +# output_dir defines the output directory to be used to save the results +output_dir: zoutput/benchmarks/mnist_benchmark + +# test domains all algorithms are tested on +test_domains: + - 0 + - 1 + +##### For random sampling ##### +# for random sampling you can exactly specify the number of samples you like to use +# per algorithm (4 algorithms with 8 hyperparameter samples each -> 4 * 8 combinations) +num_param_samples: 8 +# setting a seed for the random sampling +sampling_seed: 0 + +##### For grid search ##### +# define the mode to be grid search +mode: grid + + +# in each run the network is initialised randomly, therefore it might happen, that +# the results are different, even though the same hyperparameters were used +# to test for this it is possible to run the same hyperparameter setting multiple times +# with different random seeds used to initialise the network. +# "endseed - startseed + 1" experiments are run with the same hyperparameter sample +startseed: 0 +endseed: 5 # currently included + + +################################################################################### +# Arguments in the section domainlab_args are passed to all tasks. +# Task specific tasks take precedence. +domainlab_args: + # task specification, this could also be a task path + # (i.e. for pacs dataset tpath: examples/tasks/task_pacs_path_list.py) + task: mnistcolor10 + + # training domain for all algorithms + tr_d: + - 2 + - 3 + + # learning rate + lr: 0.001 + + # maximal number of epochs for each run + epos: 50 + + # number of iterations without process before early stopping is applied + es: 5 + + # batch size + bs: 64 + + # specification of the network to be used, this could also be a network path + # (i.e. for resnet50, npath: examples/nets/resnet50domainbed.py) + nname: conv_bn_pool_2 + + # some of the algorithms do need multiple networks, + # all of which can also be paths to a network + # (i.e. npath_... : examples/nets/resnet50domainbed.py) + nname_encoder_x2topic_h: conv_bn_pool_2 + nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 + nname_dom: conv_bn_pool_2 + + +################################################################################### +# Hyperparameters which appear in multiple tasks can e shared among these tasks. +# Hence for each task the same random sampled hyperparameters are used +Shared params: + #### For random sampling ##### + # number of shared samples to be created. + # The sampling procedure creates a set of randomly sampled shared samples, + # each algorithm which uses one of the shared samples will randomly pick its + # sample from this set. + num_shared_param_samples: 8 + # gridsearch will crash if num_shared_param_samples is set + + # shared hyperparameters: + <> + + # ... you may like to add more shared samples here like: + # gamma_y, gamma_d, zy_dim, zd_dim + + +################################################################################### +################################## TASKS ########################################## +################################################################################### +# From here on we start defining the different tasks, starting each section with +# a unique task name + +Task_Diva_Dial: + # set the method to be used, if model is skipped the Task will not be executed + model: diva + + # select a trainer to be used, if trainer is skipped adam is used + # options: "dial" or "mldg" + trainer: dial + + # Here we can also set task specific hyperparameters + # which shall be fixed among all experiments. + # f not set, the default values will be used. + zd_dim: 32 + zx_dim: 64 + gamma_d: 1e5 + + # define which hyperparameters from the shared section shall be used. + # In this task gamma_reg, zx_dim, zy_dim, zd_dim are used. + shared: + - gamma_reg + - zx_dim + - zy_dim + - zd_dim + + # define task specific hyperparameter sampling + hyperparameters: + <> + + # add constraints for your sampled hyperparameters, + # by using theire name in a python expression. + # You can use all hyperparameters defined in the hyperparameter section of + # the current task and the shared hyperparameters specified in the shared + # section of the current task + constraints: + - 'zx_dim <= zy_dim' + + +# add more tasks +Task_Jigen: + ... + +Task_Dann: + ... +``` + +## Sampling description + +There are two possible ways of choosing your hyperparameters for the benchmark in domainlab, rand sampling and grid search. The decision about which method to use was already done in the previous section be either setting `num_param_samples` (for random sampling) or `mode: grid` (for gridsearch). + +For filling in the sampling description for the into the `Shared params` and the `hyperparameter` section you have the following options: + +### uniform and loguniform distribution +1. uniform samples in the interval [min, max] +```yaml +tau: # name of the hyperparameter + min: 0.01 + max: 1 + distribution: uniform # name of the distribution + ##### for grid search ##### + num: 3 # number of grid points created for this hyperparameter +``` + +2. loguniform samples in the interval [min, max]. This is usefull if the interval spans over multiple magnitudes. +```yaml +gamma_y: # name of the hyperparameter + min: 1e4 + max: 1e6 + distribution: loguniform # name of the distribution + ##### for grid search ##### + num: 3 # number of grid points created for this hyperparameter +``` + +### normal and lognormal distribution +1. normal samples with mean and standard deviation +```yaml +pperm: # name of the hyperparameter + mean: 0.5 + std: 0.2 + distribution: normal # name of the distribution + ##### for grid search ##### + num: 3 # number of grid points created for this hyperparameter +``` + +2. lognormal samples with mean and standard deviation. This is usefull if the interval spans over multiple magnitudes. +```yaml +gamma_y: # name of the hyperparameter + mean: 1e5 + std: 2e4 + distribution: loguniform # name of the distribution + ##### for grid search ##### + num: 3 # number of grid points created for this hyperparameter +``` + +### cathegorical hyperparameters + +choose the values of the hyperparameter from a predefined list. If one uses grid search, then all values from the list are used as grid points +```yaml +nperm: # name of the hyperparameter + distribution: categorical # name of the distribution + datatype: int + values: # concrete values to choose from + - 30 + - 31 + - 100 +``` + +### Referenced hperparameters + +If one hyperparameter does directly depend on another hyperparameter you can add a reference to the other parameter. For gridsearch num will be taken from the reference, therefore it cannot be specified here. +```yaml +zy_dim: # name of the hyperparameter + reference: 2 * zx_dim # formular to be evaluated in python +``` + +### Special Arguments in the Sampling description +1. **datatype:** specify the datatype of the samples, if `int`, the values are rounded to the next integer. This works will all distributions mentioned above. + - datatypes can be set to be `int`, othervise they will be `float` +```yaml +zx_dim: # name of the hyperparameter + min: 0 + max: 96 + distribution: uniform + datatype: int # dimesions must be integer values + ##### for grid search ##### + num: 3 # number of grid points created for this hyperparameter +``` +2. **step:** if thep is specified the values are only chosen from a grid with grid size `step`. for random sampling the algorithm will randomly sample from this grid. For gridsearch the algorithm will create a subgrid of the grid with grid size `step`. +```yaml +zx_dim: # name of the hyperparameter + min: 0 + max: 96 + distribution: uniform + step: 16 # only choose from values {0, 16, 32, 84, 64, 80, 96} + datatype: int # dimesions must be integer values + ##### for grid search ##### + num: 3 # number of grid points created for this hyperparameter +``` + +## Combination of Shared and Task Specific Hyperparameter Samples + +it is possible to have all sorts of combinations: +1. a task which includes shared and task specific sampled hyperparameters +```yaml +Task_Name: + model: ... + ... + + # specify sections from the Shared params section + shared: + - ... + # specify task specific hyperparameter sampling + hyperparameters: + ... + # add the constraints to the hperparameters section + constraints: + - '...' # constraints using params from the hyperparameters and the shared section +``` + +2. Only task specific sampled hyperparameters +```yaml +Task_Name: + model: ... + ... + + # specify task specific hyperparameter sampling + hyperparameters: + ... + # add the constraints to the hperparameters section + constraints: + - '...' # constraints using only hyperparameters from the hyperparameters section +``` + +3. Only shared sampled hyperparamters +```yaml +Task_Name: + model: ... + ... + + # specify sections from the Shared params section + shared: + - ... + # add the constraints as a standalone section to the task + constraints: + - '...' # constraints using only hyperparameters from the shared section +``` + +4. No hyperparameter sampling. All Hyperparameters are either fixed to a user defined value or to the default value. No hyperparameter samples indicates no constraints. +```yaml +Task_Name: + model: ... + ... +``` diff --git a/docs/doc_custom_nn.md b/docs/doc_custom_nn.md index 7126884ba..4a91b8b64 100644 --- a/docs/doc_custom_nn.md +++ b/docs/doc_custom_nn.md @@ -1,26 +1,25 @@ -# Custom Neural Network +# Specify neural network in command line -To use a custom neural network, the user has to implement the following signature in a python file and feed into this library via `--npath`. +To use a custom neural network in command line with DomainLab, the user has to implement the following signature in a python file and specify the file path via `--npath` +```python +def build_feat_extract_net(dim_y, remove_last_layer=False): ``` -def build_feat_extract_net(dim_y, remove_last_layer): -``` +The user could choose to ignore argument `remove_last_layer` since this argument is only used in fair benchmark comparison. See examples below from `--npath=examples/nets/resnet.py` where the examples can be found in the examples folder of the code repository. - -## Custom Neural Network Examples - -### algorithm 'deepall' with custom neural network +## Example use case +### model 'erm' with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --model=erm --npath=examples/nets/resnet.py ``` -### algorithm 'matchdg' with custom neural network +### trainer 'matchdg' with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --model=erm --trainer=matchdg --epochs_ctr=3 --epos=6 --npath=examples/nets/resnet.py ``` diff --git a/docs/doc_dann.md b/docs/doc_dann.md new file mode 100644 index 000000000..576a4c668 --- /dev/null +++ b/docs/doc_dann.md @@ -0,0 +1,12 @@ +# Model DANN +## Domain Adversarial Neural Network +Details explained in the following publication: +Ganin, Yaroslav, et al. "Domain-adversarial training of neural networks." The journal of machine learning research 17.1 (2016): 2096-2030. + +
+
+ +
+
+ + diff --git a/docs/doc_diva.md b/docs/doc_diva.md index 14ddcaa38..b083e7fca 100644 --- a/docs/doc_diva.md +++ b/docs/doc_diva.md @@ -1,39 +1,44 @@ -# DIVA: Domain Invariant Variational Autoencoders +# Model DIVA +## Domain Invariant Variational Autoencoders -DIVA approaches the domain generalization problem with a variational autoencoder -with three latent variables, using three independent encoders. +DIVA addresses the domain generalization problem with a variational autoencoder +with three latent variables, using three independent encoders. -By encouraging the network to store the domain, -class and residual features in one of the latent space respectively the class specific information -shall be disentangled. +By encouraging the network to store each the domain, +class and residual features in one of the latent spaces, the class-specific information +is disentangled. -In order to obtain marginally independent latent variables, the density of the domain -and class latent space is conditioned on the domain and class respectively. These densities are parameterized -by learnable parameters. During training, all three latent variables are then fed into a single decoder -reconstructing the image. +In order to obtain marginally independent latent variables, the densities of the domain +and class latent spaces are conditioned on the domain and the class, respectively. These densities are then +parameterized by learnable parameters. During training, all three latent variables are fed into a single decoder +reconstructing the input image. Additionally, two classifiers are trained, predicting the domain and class label -from the respective latent variable, emphasizing to capture these information in this variables. +from the respective latent variable. This leads to an overall large network. However, during inference only the class encoder and classifier -is used. The experiments are showing that it is indeed possible to disentangle the information in their -test setting. - -Also in a semi-supervised setting, where class labels are missing for some data or domains, -the classification accuracy can be further improved. This is an advantage in the sense that prediction -accuracy turns out to be notably better if the training contained a domain close to the test domain. -Therefore, this semi-supervised setup allows to prepare for new domains by some additional training -needing only samples of the new domain, but no class labels. In the end however, DIVA always needs domain -labels and does not support a fully unsupervised setting. Since it is not always clear what different domains -actually exist, this can lead to problems and decreased performance. - -**Model parameters:** -the following model parameters can be specified: - -- Size of latent space for domain-specific information: zd_dim -- Size of latent space for residual variance: zx_dim -- Size of latent space for class-specific information: zy_dim -- Multiplier for y classifier ($\alpha_y$ of eq. (2) in paper below): gamma_y -- Multiplier for d classifier ($\alpha_d$ of eq. (2) in paper below): gamma_d +are used. + +DIVA can improve the classification accuracy also in a semi-supervised setting, where class labels +are missing for some data or domains. This is an advantage, as prediction +accuracy turns out to be notably better if the training data contains a domain close to the test domain. +Therefore, this semi-supervised setup allows to prepare for new domains by some additional training, +needing only samples of the new domain, but no class labels. +However, DIVA always needs domain labels and does not support a fully unsupervised setting. +Since it is not always clear which different domains actually exist, this can lead to problems and a +decreased performance. + +### Model parameters +The following hyperparameters can be specified: + +- `zd_dim`: size of latent space for domain-specific information +- `zx_dim`: size of latent space for residual variance +- `zy_dim`: size of latent space for class-specific information +- `gamma_y`: multiplier for y classifier ($\alpha_y$ of eq. (2) in paper below) +- `gamma_d`: multiplier for d classifier ($\alpha_d$ of eq. (2) in paper below) + +Furthermore, the user can specify the neural networks for the class and domain classifiers using +- `nname`/`npath` +- `nname_dom`/`npath_dom` _Reference:_ DIVA: Domain Invariant Variational Autoencoders, https://arxiv.org/pdf/1905.10427.pdf, Medical Imaging with Deep Learning. PMLR, 2020. diff --git a/docs/doc_examples.md b/docs/doc_examples.md index e48424822..21d0b2eb2 100755 --- a/docs/doc_examples.md +++ b/docs/doc_examples.md @@ -1,106 +1,128 @@ -# Examples +# Command line examples ## Colored version of MNIST ### leave one domain out -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --model=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 ``` ### choose train and test -``` -python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5 ``` ### make a sanity check for the dataset using 8 instances from each domain and from each class +```shell +python main_out.py --te_d=0 --task=mini_vlcs --debug --bs=2 --model=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 --san_check --san_num=4 ``` -python main_out.py --te_d=0 --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 --san_check --san_num=4 +### sanity check on only 2 train domains and 2 test domain2 +```shell +python main_out.py --te_d 0 1 --tr_d 3 5 --task=mnistcolor10 --debug --bs=2 --model=erm --nname=conv_bn_pool_2 --san_check --san_num=4 ``` ### generation of images -``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 --gen +```shell +python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --model=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=10e5 --gamma_d=1e5 --gen ``` ### use hduva on color mnist, train on 2 domains -``` -python main_out.py --tr_d 0 1 2 --te_d 3 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 +```shell +python main_out.py --tr_d 0 1 2 --te_d 3 --bs=2 --task=mnistcolor10 --model=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2 ``` ### hduva is domain-unsupervised, so it works also with a single domain -``` -python main_out.py --tr_d 0 --te_d 3 4 --bs=2 --task=mnistcolor10 --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 +```shell +python main_out.py --tr_d 0 --te_d 3 4 --bs=2 --task=mnistcolor10 --model=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2 ``` ## Larger images: ### model diva with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --model=diva --nname=alexnet --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 ``` ### model diva with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=diva --npath=examples/nets/resnet.py --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --model=diva --npath=examples/nets/resnet.py --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 ``` -### model deepall with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --nname=alexnet +### model erm with implemented neural network +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --model=erm --nname=alexnet ``` ### model dann with implemented neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=dann --nname=alexnet +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --model=dann --nname=alexnet ``` ### model jigen with implemented neural network +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --model=jigen --nname=alexnet --pperm=1 --nperm=100 --grid_len=3 ``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=jigen --nname=alexnet --pperm=1 --nperm=100 --grid_len=3 + + +### sannity check with jigen tile shuffling +```shell +python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=8 --model=jigen --nname=alexnet --pperm=1 --nperm=100 --grid_len=3 --san_check ``` -### model matchdg with implemented neural network +### training implemented neural network with matchdg +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --model=erm --trainer=matchdg --epochs_ctr=3 --epos=6 --nname=alexnet ``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --nname=alexnet + +### trainer matchdg with mnist +```shell + python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=erm --trainer=matchdg --nname=conv_bn_pool_2 --epochs_ctr=2 --epos=6 ``` ### hduva with implemented neural network -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 +```shell +python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --model=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2 ``` ### hduva use alex net -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=alexnet +```shell +python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --model=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --nname_encoder_sandwich_x2h4zd=alexnet ``` ## Custom Neural Network -### model deepall with custom neural network -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --aname=deepall --npath=examples/nets/resnet.py +### model erm with custom neural network +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --model=erm --npath=examples/nets/resnet.py ``` -### model matchdg with custom neural network +### trainer matchdg with custom neural network +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --bs=2 --model=erm --trainer=matchdg --epochs_ctr=3 --epos=6 --npath=examples/nets/resnet.py ``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=2 --aname=matchdg --epochs_ctr=3 --epochs_erm=3 --npath=examples/nets/resnet.py + + +### training hduva with matchdg + +```shell +python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --bs=2 --model=hduva --trainer=matchdg --epochs_ctr=3 --epos=6 --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2 ``` ### hduva use custom net for sandwich encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --npath_encoder_sandwich_layer_img2h4zd=examples/nets/resnet.py +```shell +python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --model=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --npath_encoder_sandwich_x2h4zd=examples/nets/resnet.py ``` ### hduva use custom net for topic encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --npath_topic_distrib_img2topic=examples/nets/resnet.py --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 +```shell +python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --model=hduva --nname=conv_bn_pool_2 --gamma_y=7e5 --npath_encoder_x2topic_h=examples/nets/resnet.py --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2 ``` ### hduva use custom net for classification encoder -``` -python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --npath=examples/nets/resnet.py --gamma_y=7e5 --nname_topic_distrib_img2topic=conv_bn_pool_2 --nname_encoder_sandwich_layer_img2h4zd=conv_bn_pool_2 +```shell +python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --model=hduva --npath=examples/nets/resnet.py --gamma_y=7e5 --nname_encoder_x2topic_h=conv_bn_pool_2 --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2 ``` @@ -108,36 +130,50 @@ python main_out.py --te_d=caltech --bs=2 --task=mini_vlcs --aname=hduva --npath= ### Folder Task #### Folder Task with implemented neural network -``` -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --nname=alexnet --model=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 ``` #### Folder Task with externally user defined neural network -``` -python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --npath=examples/nets/resnet.py --model=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 ``` ### ImagePath Task #### ImagePath Task with implemented algorithm -``` -python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --nname=alexnet --aname=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --nname=alexnet --model=diva --nname_dom=alexnet --gamma_y=7e5 --gamma_d=1e5 ``` #### ImagePath Task with externally user defined neural network -``` -python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --npath=examples/nets/resnet.py --aname=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 +```shell +python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --npath=examples/nets/resnet.py --model=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 ``` ## Custom algorithm defined in external python file -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/models/demo_custom_model.py --model=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet ``` -``` -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_model.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/models/demo_custom_model.py --model=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py ``` ## Adversarial images training +```shell +python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --model=erm --trainer=dial --nname=conv_bn_pool_2 ``` -python main_out.py --te_d=0 --task=mnistcolor10 --keep_model --aname=deepall_dial --nname=conv_bn_pool_2 +### Train DIVA model with DIAL trainer + +```shell +python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5 --trainer=dial +``` +### Set hyper-parameters for trainer as well +```shell +python main_out.py --te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=diva --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=1e5 --trainer=dial --dial_steps_perturb=1 +``` + +## Meta Learning Domain Generalization +```shell +python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=8 --model=erm --trainer=mldg --nname=alexnet ``` diff --git a/docs/doc_extend_contribute.md b/docs/doc_extend_contribute.md index 245ca50b3..58881d660 100644 --- a/docs/doc_extend_contribute.md +++ b/docs/doc_extend_contribute.md @@ -1,25 +1,114 @@ -# Extend or contribute with a custom domain generalization algorithm - -## External extension by implementing your custom models - -Look at this example - -``` -cd .. -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --nname_argna2val my_custom_arg_name --nname_argna2val alexnet - -python main_out.py --te_d=caltech --task=mini_vlcs --debug --bs=3 --apath=examples/algos/demo_custom_algo_builder.py --aname=custom --npath_argna2val my_custom_arg_name --npath_argna2val examples/nets/resnet.py -``` - -where the example python file corresponding to `--apath` defines a model which contains several modules that can be customized to different neural networks via `--npath_argna2val` if the neural network is specified in a python file -or `nname_argna2val` if the neural network is already implemented. +## Software Architecture and Design +![Design Diagram](libDG.svg) -## Internal extension for more advanced contribution -- implement `domainlab/algos/builder_your-algorithm-name.py` -- add your algorithm into `domainlab/algos/zoo_algos.py` by adding `chain = NodeAlgoBuilder[your-algorithm-name](chain)` -- note that all algorithms will be converted to lower case! -- make a pull request +## Code structure -### Design -![Design Diagram](libDG.svg) +domainlab/ +├── algos +│   ├── a_algo_builder.py +│   ├── builder_api_model.py +│   ├── builder_custom.py +│   ├── builder_dann.py +│   ├── builder_diva.py +│   ├── builder_erm.py +│   ├── builder_hduva.py +│   ├── builder_jigen1.py +│   ├── __init__.py +│   ├── msels +│   ├── observers +│   ├── trainers +│   ├── utils.py +│   └── zoo_algos.py +├── arg_parser.py +├── cli.py +├── compos +│   ├── a_nn_builder.py +│   ├── builder_nn_alex.py +│   ├── builder_nn_conv_bn_relu_2.py +│   ├── builder_nn_external_from_file.py +│   ├── __init__.py +│   ├── nn_zoo +│   ├── pcr +│   ├── utils_conv_get_flat_dim.py +│   ├── vae +│   └── zoo_nn.py +├── dsets +│   ├── a_dset_mnist_color_rgb_solo.py +│   ├── dset_img_path_list.py +│   ├── dset_mnist_color_solo_default.py +│   ├── dset_poly_domains_mnist_color_default.py +│   ├── dset_subfolder.py +│   ├── __init__.py +│   ├── utils_color_palette.py +│   ├── utils_data.py +│   └── utils_wrapdset_patches.py +├── exp +│   ├── exp_cuda_seed.py +│   ├── exp_main.py +│   ├── exp_utils.py +│   └── __init__.py +├── exp_protocol +│   ├── aggregate_results.py +│   ├── benchmark.smk +│   ├── __init__.py +│   └── run_experiment.py +├── __init__.py +├── mk_exp.py +├── models +│   ├── a_model_classif.py +│   ├── a_model.py +│   ├── args_jigen.py +│   ├── args_vae.py +│   ├── __init__.py +│   ├── interface_vae_xyd.py +│   ├── model_custom.py +│   ├── model_dann.py +│   ├── model_diva.py +│   ├── model_erm.py +│   ├── model_hduva.py +│   ├── model_jigen.py +│   └── model_vae_xyd_classif.py +├── tasks +│   ├── a_task_classif.py +│   ├── a_task.py +│   ├── b_task_classif.py +│   ├── b_task.py +│   ├── __init__.py +│   ├── task_dset.py +│   ├── task_folder_mk.py +│   ├── task_folder.py +│   ├── task_mini_vlcs.py +│   ├── task_mnist_color.py +│   ├── task_pathlist.py +│   ├── task_utils.py +│   ├── utils_task_dset.py +│   ├── utils_task.py +│   └── zoo_tasks.py +├── utils +│   ├── flows_gen_img_model.py +│   ├── generate_benchmark_plots.py +│   ├── get_git_tag.py +│   ├── hyperparameter_gridsearch.py +│   ├── hyperparameter_sampling.py +│   ├── __init__.py +│   ├── logger.py +│   ├── override_interface.py +│   ├── perf_metrics.py +│   ├── perf.py +│   ├── sanity_check.py +│   ├── test_img.py +│   ├── u_import_net_module.py +│   ├── u_import.py +│   ├── utils_classif.py +│   ├── utils_class.py +│   ├── utils_cuda.py +│   └── utils_img_sav.py +└── zdata + ├── mixed_codec + ├── pacs_mini_10 + ├── pacs_split + ├── patches_permutation4jigsaw + ├── script + ├── vlcs_mini + └── ztest_files diff --git a/docs/doc_install.md b/docs/doc_install.md new file mode 100644 index 000000000..c819f6e50 --- /dev/null +++ b/docs/doc_install.md @@ -0,0 +1,27 @@ +# Installation of DomainLab + +## Create a virtual environment for DomainLab (strongly recommended) + +`conda create --name domainlab_py39 python=3.9` + +then + +`conda activate domainlab_py39` + +### Install Development version via github + +Suppose you have cloned the repository and have changed directory to the cloned repository. + +```norun +pip install -r requirements.txt +``` +then + +`python setup.py install` + +#### Dependencies management +- [python-poetry](https://python-poetry.org/) and use the configuration file `pyproject.toml` in this repository. + +### Install Release +It is strongly recommended to create a virtual environment first, then +- Install via `pip install domainlab` diff --git a/docs/doc_mldg.md b/docs/doc_mldg.md new file mode 100644 index 000000000..694f4b3d8 --- /dev/null +++ b/docs/doc_mldg.md @@ -0,0 +1,4 @@ +# Trainer MLDG +## Meta Learning Domain Generalization + +Li, Da, et al. "Learning to generalize: Meta-learning for domain generalization." Proceedings of the AAAI conference on artificial intelligence. Vol. 32. No. 1. 2018. diff --git a/docs/doc_output.md b/docs/doc_output.md index 61c67e17a..345bb79f0 100644 --- a/docs/doc_output.md +++ b/docs/doc_output.md @@ -4,16 +4,16 @@ By default, this package generates outputs into a folder `zoutput` relative to t The output structure is something similar to below. ([] means the folder might or might not exist, texts inside () are comments) -``` +```text zoutput/ ├── aggrsts (aggregation of results) │ ├── task1_test_domain1_tagName.csv │ ├── task2_test_domain3_tagName.csv -│ -│ +│ +│ ├── [gen] (counterfactual image generation, only exist for generative models with "--gen" specified) │ ├── [task1_test_domain1] -│ +│ └── saved_models (persisted pytorch model) ├── task1_algo1_git-commit-hashtag1_seed_1_instance_wise_predictions.txt (instance wise prediction of the model) ├── [task1_algo1_git-commit-hashtag1_seed_1.model] (only exist if with command line argument "--keep_model") diff --git a/docs/doc_tasks.md b/docs/doc_tasks.md index fcbf7110d..3d3f0d73d 100644 --- a/docs/doc_tasks.md +++ b/docs/doc_tasks.md @@ -1,35 +1,51 @@ # Task Specification -The package offers various ways to specify the domain generalization task according to user's need. +The package offers various ways to specify a domain generalization task (where to find the data, which domain to use as training, which to test) according to user's need. -## TaskPathList +For all thress ways covered below, the user has to prepare a python file to feed via argument `--tpath` (means task path) into DomainLab. We provide example python files in our repository [see all examples here for specifying domain generalization task](https://github.com/marrlab/DomainLab/tree/master/examples/tasks) so that the user could follow the example to create their own domain generalization task specification. We provide inline comment to explain what each line is doing, as well as below in this documentation. + +## Possibility 1: Specify train and test domain dataset directly +The most straightforward way to specify a domain generalization task is, if you have already a [PyTorch Dataset](https://pytorch.org/tutorials/beginner/basics/data_tutorial.html) class for each domain: you could define a dictionary with the key being name for domain, and the value being the PyTorch Dataset you created corresponding to that domain (train and validation or only training) +[See an example python file here](https://github.com/marrlab/DomainLab/blob/master/examples/tasks/task_dset_custom.py) + +To train a ERM (Emperical Risk Minimization) network on this task: +```shell +python main_out.py --te_d domain1 --tr_d domain2 domain3 --tpath=examples/tasks/task_dset_custom.py --bs=32 --model=erm --nname=conv_bn_pool_2 +``` +here in the example, 3 domains are defined to be named "domain1", "domain2", "domain3", `--tpath` specifies where the python file specifying the task is stored, `--bs=32` use 32 as batchsize, `erm` is our nickname for ERM, `--nname` specifies a hard coded neural network in DomainLab, to use custom neural network, see related documentation. + +## Possibility 2: TaskPathList The user need to provide a python file indicating the root directories where images (data) from each domain are located, and for each domain, the user shall provide a plain text file indicating the file names. An example python file can be found in the [examples directory of the repository](https://github.com/marrlab/DomainLab/blob/master/examples/tasks/demo_task_path_list_small.py) with the corresponding data be found at [the data directory of the repository](https://github.com/marrlab/DomainLab/tree/master/data), where the text file indicating which file correspond to which class label (starting from 1) can be found at [example text file](https://github.com/marrlab/DomainLab/blob/master/data/pacs_split/art_painting_10.txt). The user should specify the location of the python file via command line arguments `--tpath` -## TaskFolder +```shell +python main_out.py --te_d=sketch --tpath=examples/tasks/demo_task_path_list_small.py --debug --bs=2 --npath=examples/nets/resnet.py --model=diva --npath_dom=examples/nets/resnet.py --gamma_y=7e5 --gamma_d=1e5 +``` + +## Possibility 3: TaskFolder In this mode, we assume there are structured folders where each folder contains all data from one domain, and each domain folder contains subfolders corresponding to different classes. See examples below. ### Data organization -To give an example, suppose we have a classification task to classify between car, dog, human, chair and bird and there are 3 data sources (domains) with folder name "folder_a", "folder_b" and "folder_c" respectively as shown below. +To give an example, suppose we have a classification task to classify between car, dog, human, chair and bird and there are 3 data sources (domains) with folder name "folder_a", "folder_b" and "folder_c" respectively as shown below. In each folder, the images are organized in sub-folders by their class. For example, "/path/to/3rd_domain/folder_c/dog" folder contains all the images of class "dog" from the 3rd domain. -It might be the case that across the different data sources the same class is named differently. For example, in the 1st data source, the class dog is stored in sub-folder named +It might be the case that across the different data sources the same class is named differently. For example, in the 1st data source, the class dog is stored in sub-folder named "hund", in the 2nd data source, the dog is stored in sub-folder named "husky" and in the 3rd data source, the dog is stored in sub-folder named "dog". It might also be the case that some classes exist in one data source but does not exist in another data source. For example, folder "/path/to/2nd_domain/folder_b" does not have a sub-folder for class "human". Folder structure of the 1st domain: -``` +```text ── /path/to/1st_domain/folder_a ├── auto ├── hund ├── mensch ├── stuhl └── vogel - + ``` Folder structure of the 2nd domain: @@ -40,7 +56,7 @@ Folder structure of the 2nd domain: ├── sit └── husky ``` -Folder structure of the 3rd domain: +Folder structure of the 3rd domain: ``` ── /path/to/3rd_domain/folder_c @@ -53,7 +69,7 @@ Folder structure of the 3rd domain: ### Specify the task with domainlab API The user is expected to implement something similar to the following code in a separate python file with a function with signature `get_task(na=None)`. -``` +```python import os from torchvision import transforms @@ -104,9 +120,10 @@ def get_task(na=None): # the package will call this function to get the task return chain ``` The domainlab function to create task in this example is `domainlab.tasks.mk_task_folder` -``` +```python from domainlab.tasks import mk_task_folder print(mk_task_folder.__doc__) +``` extensions: a python dictionary with key as the domain name and value as the file extensions of the image. @@ -129,8 +146,7 @@ of domain information so only a unique transform (composition) is allowed. isize: domainlab.tasks.ImSize(image channel, image height, image width) -dict_domain2imgroot: a python dictionary with keys as user specified domain names and values +dict_domain2imgroot: a python dictionary with keys as user specified domain names and values as the absolute path to each domain's data. taskna: user defined task name -``` diff --git a/docs/doc_usage_cmd.md b/docs/doc_usage_cmd.md new file mode 100644 index 000000000..b6320328b --- /dev/null +++ b/docs/doc_usage_cmd.md @@ -0,0 +1,40 @@ +### Basic usage +DomainLab comes with some minimal toy-dataset to test its basis functionality, see [A minimal subsample of the VLCS dataset](../data/vlcs_mini) and [an example configuration file for vlcs_mini](../examples/tasks/task_vlcs.py) + +Suppose you have cloned the repository and have the dependencies ready, change directory to this repository: + +To train a domain invariant model on the vlcs_mini task + +```shell +python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --config=examples/yaml/demo_config_single_run_diva.yaml +``` +where `--tpath` specifies the path of a user specified python file which defines the domain generalization task [see here](../examples/tasks/task_vlcs.py), `--te_d` specifies the test domain name (or index starting from 0), `--config` specifies the configurations of the domain generalization algorithms, [see here](../examples/yaml/demo_config_single_run_diva.yaml) + +#### Further usage +Alternatively, in a verbose mode without using the algorithm configuration file: + +```shell +python main_out.py --te_d=caltech --tpath=examples/tasks/task_vlcs.py --debug --bs=2 --model=diva --gamma_y=7e5 --gamma_d=1e5 --nname=alexnet --nname_dom=conv_bn_pool_2 +``` + +where `--model` specifies which algorithm to use, `--bs` specifies the batch size, `--debug` restrain only running for 2 epochs and save results with prefix 'debug'. For DIVA, the hyper-parameters include `--gamma_y=7e5` which is the relative weight of ERM loss compared to ELBO loss, and `--gamma_d=1e5`, which is the relative weight of domain classification loss compared to ELBO loss. +`--nname` is to specify which neural network to use for feature extraction for classification, `--nname_dom` is to specify which neural network to use for feature extraction of domains. +For usage of other arguments, check with + +```shell +python main_out.py --help +``` + +See also [Examples](./doc_examples.md). + +### Custom Neural network + +where the user could plugin different neural network architectures for the same algorithm. See +[Specify Custom Neural Networks for an algorithm](./doc_custom_nn.md) + +### Output structure (results storage) and Performance Measure +[Output structure and Performance Measure](./doc_output.md) + + +## Software Design Pattern, Extend or Contribution +[Extend or Contibute](./doc_extend_contribute.md) diff --git a/docs/domainlab.algos.compos.rst b/docs/domainlab.algos.compos.rst deleted file mode 100644 index 991f8693e..000000000 --- a/docs/domainlab.algos.compos.rst +++ /dev/null @@ -1,53 +0,0 @@ -domainlab.algos.compos package -============================== - -Submodules ----------- - -domainlab.algos.compos.matchdg\_args module -------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_args - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_base module -------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_base - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_ctr\_erm module ------------------------------------------------ - -.. automodule:: domainlab.algos.compos.matchdg_ctr_erm - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_match module --------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_match - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.compos.matchdg\_utils module --------------------------------------------- - -.. automodule:: domainlab.algos.compos.matchdg_utils - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos.compos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.algos.rst b/docs/domainlab.algos.rst deleted file mode 100644 index 9733ba09a..000000000 --- a/docs/domainlab.algos.rst +++ /dev/null @@ -1,104 +0,0 @@ -domainlab.algos package -======================= - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - domainlab.algos.compos - domainlab.algos.msels - domainlab.algos.observers - domainlab.algos.trainers - -Submodules ----------- - -domainlab.algos.a\_algo\_builder module ---------------------------------------- - -.. automodule:: domainlab.algos.a_algo_builder - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_custom module --------------------------------------- - -.. automodule:: domainlab.algos.builder_custom - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_dann module ------------------------------------- - -.. automodule:: domainlab.algos.builder_dann - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_deepall module ---------------------------------------- - -.. automodule:: domainlab.algos.builder_deepall - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_dial module ------------------------------------- - -.. automodule:: domainlab.algos.builder_dial - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_diva module ------------------------------------- - -.. automodule:: domainlab.algos.builder_diva - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_hduva module -------------------------------------- - -.. automodule:: domainlab.algos.builder_hduva - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_jigen1 module --------------------------------------- - -.. automodule:: domainlab.algos.builder_jigen1 - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.builder\_matchdg module ---------------------------------------- - -.. automodule:: domainlab.algos.builder_matchdg - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.zoo\_algos module ---------------------------------- - -.. automodule:: domainlab.algos.zoo_algos - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.algos.trainers.rst b/docs/domainlab.algos.trainers.rst deleted file mode 100644 index 3ac371ef2..000000000 --- a/docs/domainlab.algos.trainers.rst +++ /dev/null @@ -1,61 +0,0 @@ -domainlab.algos.trainers package -================================ - -Submodules ----------- - -domainlab.algos.trainers.a\_trainer module ------------------------------------------- - -.. automodule:: domainlab.algos.trainers.a_trainer - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.args\_dial module ------------------------------------------- - -.. automodule:: domainlab.algos.trainers.args_dial - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_basic module --------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_basic - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_dial module -------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_dial - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_matchdg module ----------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_matchdg - :members: - :undoc-members: - :show-inheritance: - -domainlab.algos.trainers.train\_visitor module ----------------------------------------------- - -.. automodule:: domainlab.algos.trainers.train_visitor - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.algos.trainers - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.compos.nn_zoo.rst b/docs/domainlab.compos.nn_zoo.rst deleted file mode 100644 index c75d6059d..000000000 --- a/docs/domainlab.compos.nn_zoo.rst +++ /dev/null @@ -1,69 +0,0 @@ -domainlab.compos.nn\_zoo package -================================ - -Submodules ----------- - -domainlab.compos.nn\_zoo.net\_adversarial module ------------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_adversarial - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.net\_classif module --------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.net\_conv\_conv\_bn\_pool\_2 module ------------------------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.net\_gated module ------------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.net_gated - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.nn module ----------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.nn - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.nn\_alex module ----------------------------------------- - -.. automodule:: domainlab.compos.nn_zoo.nn_alex - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.nn\_zoo.nn\_torchvision module ------------------------------------------------ - -.. automodule:: domainlab.compos.nn_zoo.nn_torchvision - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.compos.nn_zoo - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.compos.rst b/docs/domainlab.compos.rst deleted file mode 100644 index 7dce11821..000000000 --- a/docs/domainlab.compos.rst +++ /dev/null @@ -1,69 +0,0 @@ -domainlab.compos package -======================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - domainlab.compos.nn_zoo - -Submodules ----------- - -domainlab.compos.a\_nn\_builder module --------------------------------------- - -.. automodule:: domainlab.compos.a_nn_builder - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.builder\_nn\_alex module ------------------------------------------ - -.. automodule:: domainlab.compos.builder_nn_alex - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.builder\_nn\_conv\_bn\_relu\_2 module ------------------------------------------------------- - -.. automodule:: domainlab.compos.builder_nn_conv_bn_relu_2 - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.builder\_nn\_external\_from\_file module ---------------------------------------------------------- - -.. automodule:: domainlab.compos.builder_nn_external_from_file - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.utils\_conv\_get\_flat\_dim module ---------------------------------------------------- - -.. automodule:: domainlab.compos.utils_conv_get_flat_dim - :members: - :undoc-members: - :show-inheritance: - -domainlab.compos.zoo\_nn module -------------------------------- - -.. automodule:: domainlab.compos.zoo_nn - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.compos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.dsets.rst b/docs/domainlab.dsets.rst deleted file mode 100644 index 9de944f19..000000000 --- a/docs/domainlab.dsets.rst +++ /dev/null @@ -1,77 +0,0 @@ -domainlab.dsets package -======================= - -Submodules ----------- - -domainlab.dsets.a\_dset\_mnist\_color\_rgb\_solo module -------------------------------------------------------- - -.. automodule:: domainlab.dsets.a_dset_mnist_color_rgb_solo - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_img\_path\_list module --------------------------------------------- - -.. automodule:: domainlab.dsets.dset_img_path_list - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_mnist\_color\_solo\_default module --------------------------------------------------------- - -.. automodule:: domainlab.dsets.dset_mnist_color_solo_default - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_poly\_domains\_mnist\_color\_default module ------------------------------------------------------------------ - -.. automodule:: domainlab.dsets.dset_poly_domains_mnist_color_default - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.dset\_subfolder module --------------------------------------- - -.. automodule:: domainlab.dsets.dset_subfolder - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.utils\_color\_palette module --------------------------------------------- - -.. automodule:: domainlab.dsets.utils_color_palette - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.utils\_data module ----------------------------------- - -.. automodule:: domainlab.dsets.utils_data - :members: - :undoc-members: - :show-inheritance: - -domainlab.dsets.utils\_wrapdset\_patches module ------------------------------------------------ - -.. automodule:: domainlab.dsets.utils_wrapdset_patches - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.dsets - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.models.rst b/docs/domainlab.models.rst deleted file mode 100644 index 235c9b0cc..000000000 --- a/docs/domainlab.models.rst +++ /dev/null @@ -1,109 +0,0 @@ -domainlab.models package -======================== - -Submodules ----------- - -domainlab.models.a\_model module --------------------------------- - -.. automodule:: domainlab.models.a_model - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.a\_model\_classif module ------------------------------------------ - -.. automodule:: domainlab.models.a_model_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.args\_jigen module ------------------------------------ - -.. automodule:: domainlab.models.args_jigen - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.args\_vae module ---------------------------------- - -.. automodule:: domainlab.models.args_vae - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_custom module -------------------------------------- - -.. automodule:: domainlab.models.model_custom - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_dann module ------------------------------------ - -.. automodule:: domainlab.models.model_dann - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_deep\_all module ----------------------------------------- - -.. automodule:: domainlab.models.model_deep_all - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_diva module ------------------------------------ - -.. automodule:: domainlab.models.model_diva - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_hduva module ------------------------------------- - -.. automodule:: domainlab.models.model_hduva - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_jigen module ------------------------------------- - -.. automodule:: domainlab.models.model_jigen - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.model\_vae\_xyd\_classif module ------------------------------------------------- - -.. automodule:: domainlab.models.model_vae_xyd_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.models.wrapper\_matchdg module ----------------------------------------- - -.. automodule:: domainlab.models.wrapper_matchdg - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.models - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.rst b/docs/domainlab.rst deleted file mode 100644 index b2a98deda..000000000 --- a/docs/domainlab.rst +++ /dev/null @@ -1,35 +0,0 @@ -domainlab package -================= - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - domainlab.algos - domainlab.compos - domainlab.dsets - domainlab.exp_protocol - domainlab.models - domainlab.tasks - domainlab.utils - -Submodules ----------- - -domainlab.arg\_parser module ----------------------------- - -.. automodule:: domainlab.arg_parser - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.tasks.rst b/docs/domainlab.tasks.rst deleted file mode 100644 index a29b6f973..000000000 --- a/docs/domainlab.tasks.rst +++ /dev/null @@ -1,93 +0,0 @@ -domainlab.tasks package -======================= - -Submodules ----------- - -domainlab.tasks.a\_task\_classif module ---------------------------------------- - -.. automodule:: domainlab.tasks.a_task_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.b\_task module ------------------------------- - -.. automodule:: domainlab.tasks.b_task - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_folder module ------------------------------------ - -.. automodule:: domainlab.tasks.task_folder - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_folder\_mk module ---------------------------------------- - -.. automodule:: domainlab.tasks.task_folder_mk - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_mnist\_color module ------------------------------------------ - -.. automodule:: domainlab.tasks.task_mnist_color - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_pathlist module -------------------------------------- - -.. automodule:: domainlab.tasks.task_pathlist - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.task\_utils module ----------------------------------- - -.. automodule:: domainlab.tasks.task_utils - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.utils\_task module ----------------------------------- - -.. automodule:: domainlab.tasks.utils_task - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.utils\_task\_dset module ----------------------------------------- - -.. automodule:: domainlab.tasks.utils_task_dset - :members: - :undoc-members: - :show-inheritance: - -domainlab.tasks.zoo\_tasks module ---------------------------------- - -.. automodule:: domainlab.tasks.zoo_tasks - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.tasks - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/domainlab.utils.rst b/docs/domainlab.utils.rst deleted file mode 100644 index 5304491ea..000000000 --- a/docs/domainlab.utils.rst +++ /dev/null @@ -1,125 +0,0 @@ -domainlab.utils package -======================= - -Submodules ----------- - -domainlab.utils.flows\_gen\_img\_model module ---------------------------------------------- - -.. automodule:: domainlab.utils.flows_gen_img_model - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.generate\_benchmark\_plots module -------------------------------------------------- - -.. automodule:: domainlab.utils.generate_benchmark_plots - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.get\_git\_tag module ------------------------------------- - -.. automodule:: domainlab.utils.get_git_tag - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.hyperparameter\_sampling module ------------------------------------------------ - -.. automodule:: domainlab.utils.hyperparameter_sampling - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.override\_interface module ------------------------------------------- - -.. automodule:: domainlab.utils.override_interface - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.perf module ---------------------------- - -.. automodule:: domainlab.utils.perf - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.perf\_metrics module ------------------------------------- - -.. automodule:: domainlab.utils.perf_metrics - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.test\_img module --------------------------------- - -.. automodule:: domainlab.utils.test_img - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.u\_import module --------------------------------- - -.. automodule:: domainlab.utils.u_import - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.u\_import\_net\_module module ---------------------------------------------- - -.. automodule:: domainlab.utils.u_import_net_module - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_class module ------------------------------------ - -.. automodule:: domainlab.utils.utils_class - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_classif module -------------------------------------- - -.. automodule:: domainlab.utils.utils_classif - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_cuda module ----------------------------------- - -.. automodule:: domainlab.utils.utils_cuda - :members: - :undoc-members: - :show-inheritance: - -domainlab.utils.utils\_img\_sav module --------------------------------------- - -.. automodule:: domainlab.utils.utils_img_sav - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: domainlab.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/figs/DIAL_netw.png b/docs/figs/DIAL_netw.png new file mode 100644 index 000000000..ad864af67 Binary files /dev/null and b/docs/figs/DIAL_netw.png differ diff --git a/docs/figs/adv_example.png b/docs/figs/adv_example.png new file mode 100644 index 000000000..8bde15834 Binary files /dev/null and b/docs/figs/adv_example.png differ diff --git a/docs/figs/colored_MNIST/0/digit0.jpg b/docs/figs/colored_MNIST/0/digit0.jpg new file mode 100644 index 000000000..97a90641f Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit1.jpg b/docs/figs/colored_MNIST/0/digit1.jpg new file mode 100644 index 000000000..577bce244 Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit2.jpg b/docs/figs/colored_MNIST/0/digit2.jpg new file mode 100644 index 000000000..0114c5096 Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit3.jpg b/docs/figs/colored_MNIST/0/digit3.jpg new file mode 100644 index 000000000..c21373392 Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit4.jpg b/docs/figs/colored_MNIST/0/digit4.jpg new file mode 100644 index 000000000..e4b9efacb Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit5.jpg b/docs/figs/colored_MNIST/0/digit5.jpg new file mode 100644 index 000000000..fefee0526 Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit6.jpg b/docs/figs/colored_MNIST/0/digit6.jpg new file mode 100644 index 000000000..8232dd0ee Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit7.jpg b/docs/figs/colored_MNIST/0/digit7.jpg new file mode 100644 index 000000000..cd2944a22 Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit8.jpg b/docs/figs/colored_MNIST/0/digit8.jpg new file mode 100644 index 000000000..aea9d70ae Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/0/digit9.jpg b/docs/figs/colored_MNIST/0/digit9.jpg new file mode 100644 index 000000000..a4eadee7d Binary files /dev/null and b/docs/figs/colored_MNIST/0/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit0.jpg b/docs/figs/colored_MNIST/1/digit0.jpg new file mode 100644 index 000000000..db93d5dfa Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit1.jpg b/docs/figs/colored_MNIST/1/digit1.jpg new file mode 100644 index 000000000..c88e6aba1 Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit2.jpg b/docs/figs/colored_MNIST/1/digit2.jpg new file mode 100644 index 000000000..a0f022a58 Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit3.jpg b/docs/figs/colored_MNIST/1/digit3.jpg new file mode 100644 index 000000000..136a2361f Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit4.jpg b/docs/figs/colored_MNIST/1/digit4.jpg new file mode 100644 index 000000000..a6971bd1f Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit5.jpg b/docs/figs/colored_MNIST/1/digit5.jpg new file mode 100644 index 000000000..e82e3a318 Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit6.jpg b/docs/figs/colored_MNIST/1/digit6.jpg new file mode 100644 index 000000000..79939eea0 Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit7.jpg b/docs/figs/colored_MNIST/1/digit7.jpg new file mode 100644 index 000000000..1d588dd54 Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit8.jpg b/docs/figs/colored_MNIST/1/digit8.jpg new file mode 100644 index 000000000..da674e72a Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/1/digit9.jpg b/docs/figs/colored_MNIST/1/digit9.jpg new file mode 100644 index 000000000..fb23ca131 Binary files /dev/null and b/docs/figs/colored_MNIST/1/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit0.jpg b/docs/figs/colored_MNIST/2/digit0.jpg new file mode 100644 index 000000000..882c1397f Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit1.jpg b/docs/figs/colored_MNIST/2/digit1.jpg new file mode 100644 index 000000000..1424976de Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit2.jpg b/docs/figs/colored_MNIST/2/digit2.jpg new file mode 100644 index 000000000..ff5c82041 Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit3.jpg b/docs/figs/colored_MNIST/2/digit3.jpg new file mode 100644 index 000000000..e985e574b Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit4.jpg b/docs/figs/colored_MNIST/2/digit4.jpg new file mode 100644 index 000000000..152dac9ca Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit5.jpg b/docs/figs/colored_MNIST/2/digit5.jpg new file mode 100644 index 000000000..73dddfe36 Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit6.jpg b/docs/figs/colored_MNIST/2/digit6.jpg new file mode 100644 index 000000000..37efd8fc4 Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit7.jpg b/docs/figs/colored_MNIST/2/digit7.jpg new file mode 100644 index 000000000..46bca157a Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit8.jpg b/docs/figs/colored_MNIST/2/digit8.jpg new file mode 100644 index 000000000..95903f857 Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/2/digit9.jpg b/docs/figs/colored_MNIST/2/digit9.jpg new file mode 100644 index 000000000..41839a36f Binary files /dev/null and b/docs/figs/colored_MNIST/2/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit0.jpg b/docs/figs/colored_MNIST/3/digit0.jpg new file mode 100644 index 000000000..25a791215 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit1.jpg b/docs/figs/colored_MNIST/3/digit1.jpg new file mode 100644 index 000000000..628446e3b Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit2.jpg b/docs/figs/colored_MNIST/3/digit2.jpg new file mode 100644 index 000000000..7bcccb397 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit3.jpg b/docs/figs/colored_MNIST/3/digit3.jpg new file mode 100644 index 000000000..1c2daae60 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit4.jpg b/docs/figs/colored_MNIST/3/digit4.jpg new file mode 100644 index 000000000..97e5a3dc7 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit5.jpg b/docs/figs/colored_MNIST/3/digit5.jpg new file mode 100644 index 000000000..90ef63ba4 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit6.jpg b/docs/figs/colored_MNIST/3/digit6.jpg new file mode 100644 index 000000000..6f3ecfeab Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit7.jpg b/docs/figs/colored_MNIST/3/digit7.jpg new file mode 100644 index 000000000..765116c46 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit8.jpg b/docs/figs/colored_MNIST/3/digit8.jpg new file mode 100644 index 000000000..41b996e10 Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/3/digit9.jpg b/docs/figs/colored_MNIST/3/digit9.jpg new file mode 100644 index 000000000..20ab0c60f Binary files /dev/null and b/docs/figs/colored_MNIST/3/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit0.jpg b/docs/figs/colored_MNIST/4/digit0.jpg new file mode 100644 index 000000000..98c05b3a6 Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit1.jpg b/docs/figs/colored_MNIST/4/digit1.jpg new file mode 100644 index 000000000..506526d82 Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit2.jpg b/docs/figs/colored_MNIST/4/digit2.jpg new file mode 100644 index 000000000..c316520ad Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit3.jpg b/docs/figs/colored_MNIST/4/digit3.jpg new file mode 100644 index 000000000..afe32db77 Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit4.jpg b/docs/figs/colored_MNIST/4/digit4.jpg new file mode 100644 index 000000000..78bbead48 Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit5.jpg b/docs/figs/colored_MNIST/4/digit5.jpg new file mode 100644 index 000000000..b9a0a30f6 Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit6.jpg b/docs/figs/colored_MNIST/4/digit6.jpg new file mode 100644 index 000000000..52581d4cf Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit7.jpg b/docs/figs/colored_MNIST/4/digit7.jpg new file mode 100644 index 000000000..cb1f53c0e Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit8.jpg b/docs/figs/colored_MNIST/4/digit8.jpg new file mode 100644 index 000000000..c0305c1ed Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/4/digit9.jpg b/docs/figs/colored_MNIST/4/digit9.jpg new file mode 100644 index 000000000..4c18c7429 Binary files /dev/null and b/docs/figs/colored_MNIST/4/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit0.jpg b/docs/figs/colored_MNIST/5/digit0.jpg new file mode 100644 index 000000000..222e1f486 Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit1.jpg b/docs/figs/colored_MNIST/5/digit1.jpg new file mode 100644 index 000000000..ee7baea4a Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit2.jpg b/docs/figs/colored_MNIST/5/digit2.jpg new file mode 100644 index 000000000..d46f30820 Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit3.jpg b/docs/figs/colored_MNIST/5/digit3.jpg new file mode 100644 index 000000000..d80ef08ab Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit4.jpg b/docs/figs/colored_MNIST/5/digit4.jpg new file mode 100644 index 000000000..07c5671ed Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit5.jpg b/docs/figs/colored_MNIST/5/digit5.jpg new file mode 100644 index 000000000..8e47e7064 Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit6.jpg b/docs/figs/colored_MNIST/5/digit6.jpg new file mode 100644 index 000000000..13d5474d7 Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit7.jpg b/docs/figs/colored_MNIST/5/digit7.jpg new file mode 100644 index 000000000..42ffb32e7 Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit8.jpg b/docs/figs/colored_MNIST/5/digit8.jpg new file mode 100644 index 000000000..5cad933b7 Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/5/digit9.jpg b/docs/figs/colored_MNIST/5/digit9.jpg new file mode 100644 index 000000000..6c613d1ff Binary files /dev/null and b/docs/figs/colored_MNIST/5/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit0.jpg b/docs/figs/colored_MNIST/6/digit0.jpg new file mode 100644 index 000000000..229822e69 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit1.jpg b/docs/figs/colored_MNIST/6/digit1.jpg new file mode 100644 index 000000000..c6bcf0172 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit2.jpg b/docs/figs/colored_MNIST/6/digit2.jpg new file mode 100644 index 000000000..a84628328 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit3.jpg b/docs/figs/colored_MNIST/6/digit3.jpg new file mode 100644 index 000000000..cddd12c72 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit4.jpg b/docs/figs/colored_MNIST/6/digit4.jpg new file mode 100644 index 000000000..b668b30f1 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit5.jpg b/docs/figs/colored_MNIST/6/digit5.jpg new file mode 100644 index 000000000..b7b0ea28f Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit6.jpg b/docs/figs/colored_MNIST/6/digit6.jpg new file mode 100644 index 000000000..127e2b691 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit7.jpg b/docs/figs/colored_MNIST/6/digit7.jpg new file mode 100644 index 000000000..5559482e8 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit8.jpg b/docs/figs/colored_MNIST/6/digit8.jpg new file mode 100644 index 000000000..f71300dd3 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/6/digit9.jpg b/docs/figs/colored_MNIST/6/digit9.jpg new file mode 100644 index 000000000..10d886cf0 Binary files /dev/null and b/docs/figs/colored_MNIST/6/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit0.jpg b/docs/figs/colored_MNIST/7/digit0.jpg new file mode 100644 index 000000000..4fd0bee0f Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit1.jpg b/docs/figs/colored_MNIST/7/digit1.jpg new file mode 100644 index 000000000..efe48658c Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit2.jpg b/docs/figs/colored_MNIST/7/digit2.jpg new file mode 100644 index 000000000..29ab4161b Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit3.jpg b/docs/figs/colored_MNIST/7/digit3.jpg new file mode 100644 index 000000000..4e09453d5 Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit4.jpg b/docs/figs/colored_MNIST/7/digit4.jpg new file mode 100644 index 000000000..671837041 Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit5.jpg b/docs/figs/colored_MNIST/7/digit5.jpg new file mode 100644 index 000000000..fe02fb75a Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit6.jpg b/docs/figs/colored_MNIST/7/digit6.jpg new file mode 100644 index 000000000..0636ec686 Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit7.jpg b/docs/figs/colored_MNIST/7/digit7.jpg new file mode 100644 index 000000000..380471cbb Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit8.jpg b/docs/figs/colored_MNIST/7/digit8.jpg new file mode 100644 index 000000000..c8d669e7d Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/7/digit9.jpg b/docs/figs/colored_MNIST/7/digit9.jpg new file mode 100644 index 000000000..65fd87473 Binary files /dev/null and b/docs/figs/colored_MNIST/7/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit0.jpg b/docs/figs/colored_MNIST/8/digit0.jpg new file mode 100644 index 000000000..603f74541 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit1.jpg b/docs/figs/colored_MNIST/8/digit1.jpg new file mode 100644 index 000000000..086340463 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit2.jpg b/docs/figs/colored_MNIST/8/digit2.jpg new file mode 100644 index 000000000..92d48db81 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit3.jpg b/docs/figs/colored_MNIST/8/digit3.jpg new file mode 100644 index 000000000..9ac155ad8 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit4.jpg b/docs/figs/colored_MNIST/8/digit4.jpg new file mode 100644 index 000000000..ffbc53425 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit5.jpg b/docs/figs/colored_MNIST/8/digit5.jpg new file mode 100644 index 000000000..58f0bd0fe Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit6.jpg b/docs/figs/colored_MNIST/8/digit6.jpg new file mode 100644 index 000000000..11163210c Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit7.jpg b/docs/figs/colored_MNIST/8/digit7.jpg new file mode 100644 index 000000000..7aa86dc42 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit8.jpg b/docs/figs/colored_MNIST/8/digit8.jpg new file mode 100644 index 000000000..80908369d Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/8/digit9.jpg b/docs/figs/colored_MNIST/8/digit9.jpg new file mode 100644 index 000000000..681965fd8 Binary files /dev/null and b/docs/figs/colored_MNIST/8/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit0.jpg b/docs/figs/colored_MNIST/9/digit0.jpg new file mode 100644 index 000000000..4f175babb Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit1.jpg b/docs/figs/colored_MNIST/9/digit1.jpg new file mode 100644 index 000000000..7de95b3d2 Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit2.jpg b/docs/figs/colored_MNIST/9/digit2.jpg new file mode 100644 index 000000000..398b86369 Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit3.jpg b/docs/figs/colored_MNIST/9/digit3.jpg new file mode 100644 index 000000000..e44c2a86f Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit4.jpg b/docs/figs/colored_MNIST/9/digit4.jpg new file mode 100644 index 000000000..c4c01d252 Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit5.jpg b/docs/figs/colored_MNIST/9/digit5.jpg new file mode 100644 index 000000000..a5d457369 Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit6.jpg b/docs/figs/colored_MNIST/9/digit6.jpg new file mode 100644 index 000000000..d234500ac Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit7.jpg b/docs/figs/colored_MNIST/9/digit7.jpg new file mode 100644 index 000000000..6b3508f8b Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit8.jpg b/docs/figs/colored_MNIST/9/digit8.jpg new file mode 100644 index 000000000..157b3aec4 Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/9/digit9.jpg b/docs/figs/colored_MNIST/9/digit9.jpg new file mode 100644 index 000000000..acf56d71c Binary files /dev/null and b/docs/figs/colored_MNIST/9/digit9.jpg differ diff --git a/docs/figs/colored_MNIST/ConvMat_deepall_trd03.png b/docs/figs/colored_MNIST/ConvMat_deepall_trd03.png new file mode 100644 index 000000000..1ce65ecc3 Binary files /dev/null and b/docs/figs/colored_MNIST/ConvMat_deepall_trd03.png differ diff --git a/docs/figs/colored_MNIST/ConvMat_diva_trd03.png b/docs/figs/colored_MNIST/ConvMat_diva_trd03.png new file mode 100644 index 000000000..cd4c96c4a Binary files /dev/null and b/docs/figs/colored_MNIST/ConvMat_diva_trd03.png differ diff --git a/docs/figs/colored_MNIST/singels/digit0.jpg b/docs/figs/colored_MNIST/singels/digit0.jpg new file mode 100644 index 000000000..f3e3fed7e Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit0.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit1.jpg b/docs/figs/colored_MNIST/singels/digit1.jpg new file mode 100644 index 000000000..8c47f4e87 Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit1.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit2.jpg b/docs/figs/colored_MNIST/singels/digit2.jpg new file mode 100644 index 000000000..cee30f87c Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit2.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit3.jpg b/docs/figs/colored_MNIST/singels/digit3.jpg new file mode 100644 index 000000000..b2955fc75 Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit3.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit4.jpg b/docs/figs/colored_MNIST/singels/digit4.jpg new file mode 100644 index 000000000..bd20ba5ed Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit4.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit5.jpg b/docs/figs/colored_MNIST/singels/digit5.jpg new file mode 100644 index 000000000..54b86bcea Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit5.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit6.jpg b/docs/figs/colored_MNIST/singels/digit6.jpg new file mode 100644 index 000000000..e4bb7cb89 Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit6.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit7.jpg b/docs/figs/colored_MNIST/singels/digit7.jpg new file mode 100644 index 000000000..58e810340 Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit7.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit8.jpg b/docs/figs/colored_MNIST/singels/digit8.jpg new file mode 100644 index 000000000..20cde1ca2 Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit8.jpg differ diff --git a/docs/figs/colored_MNIST/singels/digit9.jpg b/docs/figs/colored_MNIST/singels/digit9.jpg new file mode 100644 index 000000000..a6d893156 Binary files /dev/null and b/docs/figs/colored_MNIST/singels/digit9.jpg differ diff --git a/docs/figs/dann.png b/docs/figs/dann.png new file mode 100644 index 000000000..d9cfcc421 Binary files /dev/null and b/docs/figs/dann.png differ diff --git a/docs/figs/fishr.png b/docs/figs/fishr.png new file mode 100644 index 000000000..b5ed2f25f Binary files /dev/null and b/docs/figs/fishr.png differ diff --git a/docs/figs/invarfeat4dg.png b/docs/figs/invarfeat4dg.png new file mode 100644 index 000000000..012a2ca23 Binary files /dev/null and b/docs/figs/invarfeat4dg.png differ diff --git a/docs/figs/jigen.png b/docs/figs/jigen.png new file mode 100644 index 000000000..6ea8e05e8 Binary files /dev/null and b/docs/figs/jigen.png differ diff --git a/docs/figs/matchDG_causality.png b/docs/figs/matchDG_causality.png new file mode 100644 index 000000000..824c24c06 Binary files /dev/null and b/docs/figs/matchDG_causality.png differ diff --git a/docs/figs/stochastic_variation_two_rows.png b/docs/figs/stochastic_variation_two_rows.png new file mode 100644 index 000000000..024480e0e Binary files /dev/null and b/docs/figs/stochastic_variation_two_rows.png differ diff --git a/docs/figs/tikz_hduva.svg b/docs/figs/tikz_hduva.svg index 159e7eb91..e1149b73c 100644 --- a/docs/figs/tikz_hduva.svg +++ b/docs/figs/tikz_hduva.svg @@ -531,4 +531,4 @@ transform="translate(-110.686)" id="g514" /> \ No newline at end of file + id="g516" /> diff --git a/docs/index.html b/docs/index.html index 3af30f6c1..fd99d5a8c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -19,7 +19,7 @@ - + @@ -35,6 +35,6 @@ font-family: "Roboto Mono", "Courier New", Courier, monospace } - Welcome to domainlab’s documentation! — libdg documentation + Welcome to domainlab’s documentation! — libdg documentation diff --git a/docs/index.rst b/docs/index.rst index 90fa673a2..96c8c7fe6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,10 +11,14 @@ Welcome to domainlab's documentation! :caption: Contents: modules - doc_algos docHDUVA + doc_dann docJiGen doc_diva + docMatchDG + docDIAL + docFishr + doc_mldg Indices and tables diff --git a/docs/libDG.svg b/docs/libDG.svg index 966bed82d..bfe2b405c 100644 --- a/docs/libDG.svg +++ b/docs/libDG.svg @@ -1,207 +1 @@ -taskalgostrainerobservermodel_selectiondatasetmodelcomponentsexperimentTaskdim_yTaskFolderAlgoBuilderConcreteAlgoBuilderTrainerObserverModelSelDatasetget__itemModelint dim_yint dim_dModelBuilderbuild_part_a()build_part_b()ConcreteModelConcreteModelBuildercommon_networkspatternsExperimentTaskHandler \ No newline at end of file +tasksalgostrainersobservermodel_selectiondatasetsmodelsexperimentTasktransformationsdatasets (training domains)datasets (test domains)TaskFolderTaskPathListAlgoBuilderbuild_model()build_trainer()build_observer()model_specific_task_processing()ConcreteAlgoBuilderbuild_model()build_trainer()build_observer()model_specific_task_processing()Trainermodelobservertaskupdate_regularization_weight()update_model_parameter()calculate_loss()Observertrainer.model.calculate_metric()ModelSelearly_stopDataset__get__item__()YMLConfigurationModelextract_feature()calculate_task_loss()calculate_regularization_loss()calculate_metric()ModelBuilderbuild_model_componet()ConcreteModelcalculate_regularization_loss()extract_feature()ConcreteModelBuildernetworksExperimenttasktrainerexecute()TaskHandlerAlgoHandlerUserInputtaskhyperparametersread_yml_for_configuration()command_line_arguments()benchmarkrun_experiment()plot_results()read_yml_for_configuration() diff --git a/docs/tips.txt b/docs/tips.txt new file mode 100644 index 000000000..5449e1e74 --- /dev/null +++ b/docs/tips.txt @@ -0,0 +1,2 @@ +- change conf.py to change the tabs in the website +- change index.rst to change the left navigation bar (list of algoritms) diff --git a/domainlab/__init__.py b/domainlab/__init__.py index 4a1562ae9..3388c7292 100644 --- a/domainlab/__init__.py +++ b/domainlab/__init__.py @@ -1,10 +1,23 @@ +""" +globals for the whole package +""" __docformat__ = "restructuredtext" +import torch -algos = { - "deepall": "Pool all domains together and train an ERM (empirical risk minimization) model", - "diva": "DIVA: Domain Invariant Variational Autoencoders, https://arxiv.org/pdf/1905.10427.pdf", - "hduva": "Hierarchical Variational Auto-Encoding for Unsupervised Domain Generalization:https://arxiv.org/pdf/2101.09436.pdf", - "dann": "Domain adversarial invariant feature learning", - "jigsaw": "Domain Generalization by Solving Jigsaw Puzzles, https://arxiv.org/abs/1903.06864", - "matchdg": "Domain Generalization using Causal Matching, https://arxiv.org/abs/2006.07500" -} +g_inst_component_loss_agg = torch.sum +g_tensor_batch_agg = torch.sum +g_list_loss_agg = sum + +g_name_num_shared_param_samples_rand_search = "num_shared_param_samples" + +def g_list_model_penalized_reg_agg(list_penalized_reg): + """ + aggregate along the list, but do not diminish the batch structure of the tensor + """ + return torch.stack(list_penalized_reg, dim=0).sum(dim=0) + + +g_str_cross_entropy_agg = "none" +# component loss refers to aggregation of pixel loss, digit of KL divergences loss +# instance loss currently use torch.sum, which is the same effect as torch.mean, the +# important part is the component aggregation method inside a single instance diff --git a/domainlab/algos/a_algo_builder.py b/domainlab/algos/a_algo_builder.py index d31762c5d..f51184f3b 100644 --- a/domainlab/algos/a_algo_builder.py +++ b/domainlab/algos/a_algo_builder.py @@ -1,18 +1,18 @@ +""" +parent class for combing model, trainer, task, observer +""" +import abc + from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler +from domainlab.utils.logger import Logger class NodeAlgoBuilder(AbstractChainNodeHandler): """ Base class for Algorithm Builder """ - na_prefix = "NodeAlgoBuilder" - def dset_decoration_args_algo(self, args, ddset): - """ - most algorithms do not need re-organization of data feed flow like JiGen and MatchDG - """ - print("processing dataset for ", args.aname) - return ddset + na_prefix = "NodeAlgoBuilder" @property def name(self): @@ -24,8 +24,11 @@ def name(self): na_class = type(self).__name__ if na_class[:len_prefix] != na_prefix: raise RuntimeError( - "algorithm builder node class must start with ", na_prefix, - "the current class is named: ", na_class) + "algorithm builder node class must start with ", + na_prefix, + "the current class is named: ", + na_class, + ) return type(self).__name__[len_prefix:].lower() def is_myjob(self, request): @@ -34,5 +37,28 @@ def is_myjob(self, request): """ return request == self.name + @abc.abstractmethod def init_business(self, exp): - raise NotImplementedError + """ + combine model, trainer, observer, task + """ + + def extend(self, node): + """ + Extends the current algorithm builder with a new node. + + This method updates the builder by setting the `next_model` attribute to the specified node. + + Args: + node: The node to be added to the algorithm builder. + """ + self.next_model = node + + def init_next_model(self, model, exp): + """ + initialize the next model and decorate with current model + """ + if self.next_model is not None: + _, next_model, *_ = self.next_model.init_business(exp) + model.extend(next_model) + return model diff --git a/domainlab/algos/builder_api_model.py b/domainlab/algos/builder_api_model.py new file mode 100644 index 000000000..07c087e3b --- /dev/null +++ b/domainlab/algos/builder_api_model.py @@ -0,0 +1,26 @@ +""" +build algorithm from API coded model with custom backbone +""" +from domainlab.algos.a_algo_builder import NodeAlgoBuilder +from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf +from domainlab.algos.observers.b_obvisitor import ObVisitor +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter +from domainlab.utils.utils_cuda import get_device + + +class NodeAlgoBuilderAPIModel(NodeAlgoBuilder): + """ + build algorithm from API coded model with custom backbone + """ + + def init_business(self, exp): + """ + return trainer, model, observer + """ + args = exp.args + device = get_device(args) + model_sel = MSelOracleVisitor(MSelValPerf(max_es=args.es)) + observer = ObVisitor(model_sel) + trainer = TrainerChainNodeGetter(args.trainer)(default="hyperscheduler") + return trainer, None, observer, device diff --git a/domainlab/algos/builder_custom.py b/domainlab/algos/builder_custom.py index 8b213865f..9c50110b7 100644 --- a/domainlab/algos/builder_custom.py +++ b/domainlab/algos/builder_custom.py @@ -1,18 +1,28 @@ from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf from domainlab.algos.observers.b_obvisitor import ObVisitor -from domainlab.algos.trainers.train_basic import TrainerBasic +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter from domainlab.utils.utils_cuda import get_device +from domainlab.compos.nn_zoo.nn import LayerId def make_basic_trainer(class_name_model): """make_basic_trainer. :param class_name_model: """ + class NodeAlgoBuilderCustom(NodeAlgoBuilder): """NodeAlgoBuilderCustom.""" + + def get_trainer(self, args): + """ + chain of responsibility pattern for fetching trainer from commandline parsed arguments + """ + trainer = TrainerChainNodeGetter(args.trainer)(default="basic") + return trainer + def _set_args(self, args, val_arg_na, prefix, argname): """_set_args. Since we could not hard code all possible strings in the argparser, @@ -26,7 +36,7 @@ def _set_args(self, args, val_arg_na, prefix, argname): python main_out.py –te_d=caltech –task=mini_vlcs –debug –bs=3 –apath=examples/algos/demo_custom_model.py - –aname=custom –nname_argna2val net1 –nname_argna2val alexnet + –model=custom –nname_argna2val net1 –nname_argna2val alexnet :param args: the namespace of command line arguemnts :param val_arg_na: the custom argument name the user specified @@ -35,20 +45,21 @@ def _set_args(self, args, val_arg_na, prefix, argname): :param argname: nname_argna2val or "npath_argna2val", hard coded """ if getattr(args, argname) is None: - setattr(args, prefix+val_arg_na, None) + setattr(args, prefix + val_arg_na, None) return list_args = getattr(args, argname) ind = list_args.index(val_arg_na) - if ind+1 >= len(list_args): # list of args always even length - raise RuntimeError("\n nname_argna2val or npath_argna2val should \ + if ind + 1 >= len(list_args): # list of args always even length + raise RuntimeError( + f"\n nname_argna2val or npath_argna2val should \ \n always be specified in pairs instead of \ odd number:\ - \n %s" % ( - str(list_args))) - val = list_args[ind+1] + \n {str(list_args)}" + ) + val = list_args[ind + 1] # add attributes to namespaces args, the attributes are provided by # user in the custom model file - setattr(args, prefix+val_arg_na, val) + setattr(args, prefix + val_arg_na, val) def set_nets_from_dictionary(self, args, task, model): """set_nets_from_dictionary. @@ -57,27 +68,34 @@ def set_nets_from_dictionary(self, args, task, model): {"net1":"name1", "net2":"name2"} python main_out.py –te_d=caltech –task=mini_vlcs –debug –bs=3 –apath=examples/algos/demo_custom_model.py - –aname=custom –nname_argna2val net1 –nname_argna2val alexnet + –model=custom –nname_argna2val net1 –nname_argna2val alexnet """ - for key_module_na, val_arg_na in \ - model.dict_net_module_na2arg_na.items(): + for key_module_na, val_arg_na in model.dict_net_module_na2arg_na.items(): # - if args.nname_argna2val is None and \ - args.npath_argna2val is None: - raise RuntimeError("either specify nname_argna2val or \ - npath_argna2val") + if args.nname_argna2val is None and args.npath_argna2val is None: + raise RuntimeError( + "either specify nname_argna2val or \ + npath_argna2val" + ) self._set_args(args, val_arg_na, "nname", "nname_argna2val") self._set_args(args, val_arg_na, "npath", "npath_argna2val") # builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname"+val_arg_na, - arg_path_of_net="npath"+val_arg_na)() - + args, + arg_name_of_net="nname" + val_arg_na, + arg_path_of_net="npath" + val_arg_na, + )() net = builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, i_h=task.isize.i_h, i_w=task.isize.i_w) + flag_pretrain=True, + dim_out=task.dim_y, + remove_last_layer=False, + args=args, + isize=(task.isize.i_c, task.isize.i_h, task.isize.i_w), + ) model.add_module("%s" % (key_module_na), net) + # FIXME: this is just a stub to let net_aux be invariant feature + model._net_invar_feat = model.net_aux + model._net_classifier = LayerId() def init_business(self, exp): """ @@ -85,11 +103,14 @@ def init_business(self, exp): """ task = exp.task args = exp.args - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, model_sel, device) - model = class_name_model(list_str_y=task.list_str_y) + device = get_device(args) + model_sel = MSelOracleVisitor(MSelValPerf(max_es=args.es)) + observer = ObVisitor(model_sel) + model = class_name_model(net_classifier=None, list_str_y=task.list_str_y) + model = self.init_next_model(model, exp) self.set_nets_from_dictionary(args, task, model) - trainer = TrainerBasic(model, task, observer, device, args) - return trainer + trainer = self.get_trainer(args) + trainer.init_business(model, task, observer, device, args) + return trainer, model, observer, device + return NodeAlgoBuilderCustom diff --git a/domainlab/algos/builder_dann.py b/domainlab/algos/builder_dann.py index 74b23c9f3..d026a5bb1 100644 --- a/domainlab/algos/builder_dann.py +++ b/domainlab/algos/builder_dann.py @@ -2,13 +2,12 @@ builder for Domain Adversarial Neural Network: accept different training scheme """ from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf from domainlab.algos.observers.b_obvisitor import ObVisitor from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp -from domainlab.algos.trainers.train_visitor import TrainerVisitor -from domainlab.algos.trainers.train_visitor import HyperSchedulerAneal -from domainlab.algos.trainers.train_dial import TrainerDIAL +from domainlab.algos.trainers.hyper_scheduler import HyperSchedulerWarmupExponential +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter from domainlab.compos.nn_zoo.net_classif import ClassifDropoutReluLinear from domainlab.compos.utils_conv_get_flat_dim import get_flat_dim from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter @@ -20,51 +19,71 @@ class NodeAlgoBuilderDANN(NodeAlgoBuilder): """ NodeAlgoBuilderDANN """ + def init_business(self, exp): """ return trainer, model, observer """ task = exp.task + self._task = task args = exp.args - device = get_device(args.nocu) - msel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, msel, device) + task.get_list_domains_tr_te(args.tr_d, args.te_d) + device = get_device(args) + msel = MSelOracleVisitor(MSelValPerf(max_es=args.es)) + observer = ObVisitor(msel) observer = ObVisitorCleanUp(observer) builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, @FIXME, constant string + args, arg_name_of_net="nname", arg_path_of_net="npath" + )() # request, @FIXME, constant string net_encoder = builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_w=task.isize.i_w, - i_h=task.isize.i_h) + flag_pretrain=True, + dim_out=task.dim_y, + remove_last_layer=False, + args=args, + isize=(task.isize.i_c, task.isize.i_w, task.isize.i_h), + ) - dim_feat = get_flat_dim(net_encoder, - task.isize.i_c, - task.isize.i_h, - task.isize.i_w) + dim_feat = get_flat_dim( + net_encoder, task.isize.i_c, task.isize.i_h, task.isize.i_w + ) net_classifier = ClassifDropoutReluLinear(dim_feat, task.dim_y) - net_discriminator = ClassifDropoutReluLinear( - dim_feat, len(task.list_domain_tr)) - model = mk_dann()(list_str_y=task.list_str_y, - list_str_d=task.list_domain_tr, - alpha=args.gamma_reg, - net_encoder=net_encoder, - net_classifier=net_classifier, - net_discriminator=net_discriminator) - if args.trainer == "dial": - trainer = TrainerDIAL(model, task, observer, device, args) - elif args.trainer is None: - trainer = TrainerVisitor(model, task, observer, device, args) - trainer.set_scheduler(HyperSchedulerAneal, - total_steps=trainer.num_batches*args.epos, - flag_update_epoch=False, - flag_update_batch=True) - else: - raise RuntimeError("no other trainer supported yet for the selected algorithm") - return trainer + net_discriminator = self.reset_aux_net(net_encoder) + model = mk_dann(list_str_y=task.list_str_y, + net_classifier=net_classifier)( + list_d_tr=task.list_domain_tr, + alpha=args.gamma_reg, + net_encoder=net_encoder, + net_discriminator=net_discriminator, + builder=self) + + model = self.init_next_model(model, exp) + trainer = TrainerChainNodeGetter(args.trainer)(default="hyperscheduler") + trainer.init_business(model, task, observer, device, args) + if trainer.name == "hyperscheduler": + trainer.set_scheduler( + HyperSchedulerWarmupExponential, + total_steps=trainer.num_batches * args.warmup, + flag_update_epoch=False, + flag_update_batch=True, + ) + return trainer, model, observer, device + + def reset_aux_net(self, net_encoder): + """ + reset auxilliary neural network from task + note that net_encoder can also be a method like extract_semantic_feat + """ + dim_feat = get_flat_dim( + net_encoder, + self._task.isize.i_c, + self._task.isize.i_h, + self._task.isize.i_w, + ) + net_discriminator = ClassifDropoutReluLinear( + dim_feat, len(self._task.list_domain_tr) + ) + return net_discriminator diff --git a/domainlab/algos/builder_deepall.py b/domainlab/algos/builder_deepall.py deleted file mode 100644 index b282061fd..000000000 --- a/domainlab/algos/builder_deepall.py +++ /dev/null @@ -1,34 +0,0 @@ -from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss -from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor -from domainlab.algos.observers.b_obvisitor import ObVisitor -from domainlab.algos.trainers.train_basic import TrainerBasic -from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter -from domainlab.models.model_deep_all import mk_deepall -from domainlab.utils.utils_cuda import get_device - - -class NodeAlgoBuilderDeepAll(NodeAlgoBuilder): - def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, model_sel, device) - - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME, constant string - - net = builder.init_business(flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_h=task.isize.i_h, - i_w=task.isize.i_w) - - model = mk_deepall()(net, list_str_y=task.list_str_y) - trainer = TrainerBasic(model, task, observer, device, args) - return trainer diff --git a/domainlab/algos/builder_dial.py b/domainlab/algos/builder_dial.py deleted file mode 100644 index d289d8c63..000000000 --- a/domainlab/algos/builder_dial.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -builder for domain invariant adversarial learning -""" -from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss -from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor -from domainlab.algos.observers.b_obvisitor import ObVisitor -from domainlab.algos.trainers.train_dial import TrainerDIAL -from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter -from domainlab.models.model_deep_all import mk_deepall -from domainlab.utils.utils_cuda import get_device - - -class NodeAlgoBuilderDeepAll_DIAL(NodeAlgoBuilder): - """ - builder for domain invariant adversarial learning - """ - def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, model_sel, device) - - builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME, constant string - - net = builder.init_business(flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_h=task.isize.i_h, - i_w=task.isize.i_w) - - model = mk_deepall()(net, list_str_y=task.list_str_y) - trainer = TrainerDIAL(model, task, observer, device, args) - return trainer diff --git a/domainlab/algos/builder_diva.py b/domainlab/algos/builder_diva.py index f6e471cc9..38ceb6e9e 100644 --- a/domainlab/algos/builder_diva.py +++ b/domainlab/algos/builder_diva.py @@ -2,14 +2,12 @@ Builder pattern to build different component for experiment with DIVA """ from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf from domainlab.algos.observers.b_obvisitor import ObVisitor from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp from domainlab.algos.observers.c_obvisitor_gen import ObVisitorGen -from domainlab.algos.trainers.train_visitor import TrainerVisitor -from domainlab.algos.trainers.train_dial import TrainerDIAL - +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter from domainlab.compos.pcr.request import RequestVAEBuilderCHW from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter from domainlab.models.model_diva import mk_diva @@ -20,42 +18,43 @@ class NodeAlgoBuilderDIVA(NodeAlgoBuilder): """ Builder pattern to build different component for experiment with DIVA """ + + def get_trainer(self, args): + """ + chain of responsibility pattern for fetching trainer from dictionary + """ + trainer = TrainerChainNodeGetter(args.trainer)(default="hyperscheduler") + return trainer + def init_business(self, exp): """ return trainer, model, observer """ task = exp.task args = exp.args - request = RequestVAEBuilderCHW( - task.isize.c, task.isize.h, task.isize.w, args) + request = RequestVAEBuilderCHW(task.isize.c, task.isize.h, task.isize.w, args) node = VAEChainNodeGetter(request)() - model = mk_diva()(node, - zd_dim=args.zd_dim, - zy_dim=args.zy_dim, - zx_dim=args.zx_dim, - list_str_y=task.list_str_y, - list_d_tr=task.list_domain_tr, - gamma_d=args.gamma_d, - gamma_y=args.gamma_y, - beta_x=args.beta_x, - beta_y=args.beta_y, - beta_d=args.beta_d) - device = get_device(args.nocu) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) + task.get_list_domains_tr_te(args.tr_d, args.te_d) + model = mk_diva(list_str_y=task.list_str_y)( + node, + zd_dim=args.zd_dim, + zy_dim=args.zy_dim, + zx_dim=args.zx_dim, + list_d_tr=task.list_domain_tr, + gamma_d=args.gamma_d, + gamma_y=args.gamma_y, + beta_x=args.beta_x, + beta_y=args.beta_y, + beta_d=args.beta_d, + ) + device = get_device(args) + model_sel = MSelOracleVisitor(MSelValPerf(max_es=args.es)) if not args.gen: - observer = ObVisitorCleanUp( - ObVisitor(exp, - model_sel, - device)) - else: - observer = ObVisitorCleanUp( - ObVisitorGen(exp, - model_sel, - device)) - if args.trainer == "dial": - trainer = TrainerDIAL(model, task, observer, device, args) - elif args.trainer is None: - trainer = TrainerVisitor(model, task, observer, device, args) + observer = ObVisitor(model_sel) else: - raise NotImplementedError("diva does not support trainers other than default and dial") - return trainer + observer = ObVisitorGen(model_sel) + + observer = ObVisitorCleanUp(observer) + trainer = self.get_trainer(args) + model = self.init_next_model(model, exp) + return trainer, model, observer, device diff --git a/domainlab/algos/builder_erm.py b/domainlab/algos/builder_erm.py new file mode 100644 index 000000000..4e76670c0 --- /dev/null +++ b/domainlab/algos/builder_erm.py @@ -0,0 +1,51 @@ +""" +builder for erm +""" +from domainlab.algos.a_algo_builder import NodeAlgoBuilder +from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf +from domainlab.algos.observers.b_obvisitor import ObVisitor +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter +from domainlab.algos.utils import split_net_feat_last +from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter +from domainlab.models.model_erm import mk_erm +from domainlab.utils.utils_cuda import get_device + + +class NodeAlgoBuilderERM(NodeAlgoBuilder): + """ + builder for erm + """ + + def init_business(self, exp): + """ + return trainer, model, observer + """ + task = exp.task + args = exp.args + device = get_device(args) + model_sel = MSelOracleVisitor(MSelValPerf(max_es=args.es)) + observer = ObVisitor(model_sel) + + builder = FeatExtractNNBuilderChainNodeGetter( + args, arg_name_of_net="nname", arg_path_of_net="npath" + )() # request, # @FIXME, constant string + + net = builder.init_business( + flag_pretrain=True, + dim_out=task.dim_y, + remove_last_layer=False, + args=args, + isize=(task.isize.i_c, task.isize.i_h, task.isize.i_w), + ) + + _, _ = split_net_feat_last(net) + + model = mk_erm(list_str_y=task.list_str_y)( + net=net + # net_feat=net_invar_feat, net_classifier=net_classifier, + ) + model = self.init_next_model(model, exp) + trainer = TrainerChainNodeGetter(args.trainer)(default="basic") + # trainer.init_business(model, task, observer, device, args) + return trainer, model, observer, device diff --git a/domainlab/algos/builder_hduva.py b/domainlab/algos/builder_hduva.py index 050ee93cc..80e4526cb 100644 --- a/domainlab/algos/builder_hduva.py +++ b/domainlab/algos/builder_hduva.py @@ -1,9 +1,12 @@ +""" +build hduva model, get trainer from cmd arguments +""" from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf from domainlab.algos.observers.b_obvisitor import ObVisitor from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp -from domainlab.algos.trainers.train_visitor import TrainerVisitor +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter from domainlab.compos.pcr.request import RequestVAEBuilderCHW from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter from domainlab.models.model_hduva import mk_hduva @@ -14,32 +17,34 @@ class NodeAlgoBuilderHDUVA(NodeAlgoBuilder): """ NodeAlgoBuilderHDUVA """ + def init_business(self, exp): """ return trainer, model, observer """ task = exp.task args = exp.args - request = RequestVAEBuilderCHW( - task.isize.c, task.isize.h, task.isize.w, args) - device = get_device(args.nocu) + task.get_list_domains_tr_te(args.tr_d, args.te_d) + request = RequestVAEBuilderCHW(task.isize.c, task.isize.h, task.isize.w, args) + device = get_device(args) node = VAEChainNodeGetter(request, args.topic_dim)() - model = mk_hduva()(node, - zd_dim=args.zd_dim, - zy_dim=args.zy_dim, - zx_dim=args.zx_dim, - device=device, - topic_dim=args.topic_dim, - list_str_y=task.list_str_y, - list_d_tr=task.list_domain_tr, - gamma_d=args.gamma_d, - gamma_y=args.gamma_y, - beta_t=args.beta_t, - beta_x=args.beta_x, - beta_y=args.beta_y, - beta_d=args.beta_d) - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitorCleanUp( - ObVisitor(exp, model_sel, device)) - trainer = TrainerVisitor(model, task, observer, device, args) - return trainer + model = mk_hduva(list_str_y=task.list_str_y)( + node, + zd_dim=args.zd_dim, + zy_dim=args.zy_dim, + zx_dim=args.zx_dim, + device=device, + topic_dim=args.topic_dim, + gamma_d=args.gamma_d, + gamma_y=args.gamma_y, + beta_t=args.beta_t, + beta_x=args.beta_x, + beta_y=args.beta_y, + beta_d=args.beta_d, + ) + model = self.init_next_model(model, exp) + model_sel = MSelOracleVisitor(MSelValPerf(max_es=args.es)) + observer = ObVisitorCleanUp(ObVisitor(model_sel)) + trainer = TrainerChainNodeGetter(args.trainer)(default="hyperscheduler") + trainer.init_business(model, task, observer, device, args) + return trainer, model, observer, device diff --git a/domainlab/algos/builder_jigen1.py b/domainlab/algos/builder_jigen1.py index 5e4d5853d..4f402c128 100644 --- a/domainlab/algos/builder_jigen1.py +++ b/domainlab/algos/builder_jigen1.py @@ -2,34 +2,25 @@ builder for JiGen """ from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf from domainlab.algos.observers.b_obvisitor import ObVisitor from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp -from domainlab.algos.trainers.train_visitor import TrainerVisitor -from domainlab.algos.trainers.train_visitor import HyperSchedulerAneal +from domainlab.algos.trainers.hyper_scheduler import HyperSchedulerWarmupExponential +from domainlab.algos.trainers.train_hyper_scheduler import TrainerHyperScheduler +from domainlab.algos.trainers.zoo_trainer import TrainerChainNodeGetter from domainlab.compos.nn_zoo.net_classif import ClassifDropoutReluLinear from domainlab.compos.utils_conv_get_flat_dim import get_flat_dim from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter +from domainlab.dsets.utils_wrapdset_patches import WrapDsetPatches from domainlab.models.model_jigen import mk_jigen from domainlab.utils.utils_cuda import get_device -from domainlab.dsets.utils_wrapdset_patches import WrapDsetPatches class NodeAlgoBuilderJiGen(NodeAlgoBuilder): """ NodeAlgoBuilderJiGen """ - def dset_decoration_args_algo(self, args, ddset): - """ - JiGen need to shuffle the tiles of the original image - """ - ddset = WrapDsetPatches(ddset, - num_perms2classify=args.nperm, - prob_no_perm=1-args.pperm, - grid_len=args.grid_len, - ppath=args.jigen_ppath) - return ddset def init_business(self, exp): """ @@ -37,42 +28,48 @@ def init_business(self, exp): """ task = exp.task args = exp.args - device = get_device(args.nocu) - msel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, msel, device) + device = get_device(args) + msel = MSelOracleVisitor(msel=MSelValPerf(max_es=args.es)) + observer = ObVisitor(msel) observer = ObVisitorCleanUp(observer) builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name_of_net="nname", - arg_path_of_net="npath")() # request, @FIXME, constant string + args, arg_name_of_net="nname", arg_path_of_net="npath" + )() # request, @FIXME, constant string net_encoder = builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, - i_w=task.isize.i_w, - i_h=task.isize.i_h) + flag_pretrain=True, + dim_out=task.dim_y, + remove_last_layer=False, + args=args, + isize=(task.isize.i_c, task.isize.i_w, task.isize.i_h), + ) - dim_feat = get_flat_dim(net_encoder, - task.isize.i_c, - task.isize.i_h, - task.isize.i_w) + dim_feat = get_flat_dim( + net_encoder, task.isize.i_c, task.isize.i_h, task.isize.i_w + ) net_classifier = ClassifDropoutReluLinear(dim_feat, task.dim_y) # @FIXME: this seems to be the only difference w.r.t. builder_dann - net_classifier_perm = ClassifDropoutReluLinear( - dim_feat, args.nperm+1) - model = mk_jigen()(list_str_y=task.list_str_y, - list_str_d=task.list_domain_tr, - coeff_reg=args.gamma_reg, - net_encoder=net_encoder, - net_classifier_class=net_classifier, - net_classifier_permutation=net_classifier_perm) - - trainer = TrainerVisitor(model, task, observer, device, args) - trainer.set_scheduler(HyperSchedulerAneal, - total_steps=trainer.num_batches*args.epos, - flag_update_epoch=False, - flag_update_batch=True) - return trainer + net_classifier_perm = ClassifDropoutReluLinear(dim_feat, args.nperm + 1) + model = mk_jigen( + list_str_y=task.list_str_y, + net_classifier=net_classifier)( + coeff_reg=args.gamma_reg, + net_encoder=net_encoder, + net_classifier_permutation=net_classifier_perm, + n_perm=args.nperm, + prob_permutation=args.pperm, + ) + model = self.init_next_model(model, exp) + trainer = TrainerChainNodeGetter(args.trainer)(default="hyperscheduler") + trainer.init_business(model, task, observer, device, args) + if isinstance(trainer, TrainerHyperScheduler): + trainer.set_scheduler( + HyperSchedulerWarmupExponential, + total_steps=trainer.num_batches * args.warmup, + flag_update_epoch=False, + flag_update_batch=True, + ) + return trainer, model, observer, device diff --git a/domainlab/algos/builder_matchdg.py b/domainlab/algos/builder_matchdg.py deleted file mode 100644 index 54326334e..000000000 --- a/domainlab/algos/builder_matchdg.py +++ /dev/null @@ -1,65 +0,0 @@ -from domainlab.algos.a_algo_builder import NodeAlgoBuilder -from domainlab.algos.msels.c_msel import MSelTrLoss -from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor -from domainlab.algos.observers.b_obvisitor import ObVisitor -from domainlab.algos.trainers.train_matchdg import TrainerMatchDG -from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter -from domainlab.models.model_deep_all import mk_deepall -from domainlab.models.wrapper_matchdg import ModelWrapMatchDGLogit -from domainlab.utils.utils_cuda import get_device -from domainlab.tasks.utils_task_dset import DsetIndDecorator4XYD - - -class NodeAlgoBuilderMatchDG(NodeAlgoBuilder): - """ - algorithm builder for matchDG - """ - def dset_decoration_args_algo(self, args, ddset): - ddset = DsetIndDecorator4XYD(ddset) - return ddset - - def init_business(self, exp): - """ - return trainer, model, observer - """ - task = exp.task - args = exp.args - device = get_device(args.nocu) - - erm_builder = FeatExtractNNBuilderChainNodeGetter( - args, - arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME: constant string - erm_net = erm_builder.init_business( - flag_pretrain=True, dim_out=task.dim_y, - remove_last_layer=False, args=args, - i_c=task.isize.i_c, i_h=task.isize.i_h, - i_w=task.isize.i_w) - - model = mk_deepall()(erm_net, list_str_y=task.list_str_y) - model = ModelWrapMatchDGLogit(model, list_str_y=task.list_str_y) - - model = model.to(device) - ctr_builder = FeatExtractNNBuilderChainNodeGetter( - args, - arg_name_of_net="nname", - arg_path_of_net="npath")() # request, # @FIXME constant string - ctr_net = ctr_builder.init_business( - flag_pretrain=True, - dim_out=task.dim_y, - # @FIXME: ctr_model should not rely on task.dim_y so it could - # support more tasks? maybe use task.feat_num? - remove_last_layer=True, - args=args, - i_c=task.isize.i_c, - i_h=task.isize.i_h, - i_w=task.isize.i_w) - ctr_model = ctr_net.to(device) - - model_sel = MSelOracleVisitor(MSelTrLoss(max_es=args.es)) - observer = ObVisitor(exp, - model_sel, - device) - trainer = TrainerMatchDG(exp, task, ctr_model, model, observer, args, - device) - return trainer diff --git a/domainlab/algos/compos/matchdg_args.py b/domainlab/algos/compos/matchdg_args.py deleted file mode 100644 index 119754708..000000000 --- a/domainlab/algos/compos/matchdg_args.py +++ /dev/null @@ -1,15 +0,0 @@ -def add_args2parser_matchdg(parser): - # parser = argparse.ArgumentParser() - parser.add_argument('--tau', type=int, default=0.05, - help='factor to magnify cosine similarity') - parser.add_argument('--epos_per_match_update', type=int, default=5, - help='Number of epochs before updating the match tensor') - parser.add_argument('--epochs_ctr', type=int, default=None, - help='Total number of epochs for ctr') - parser.add_argument('--epochs_erm', type=int, default=None, - help='Total number of epochs for erm') - parser.add_argument('--penalty_ws', type=float, default=0.1, - help='Penalty weight for Matching Loss') - # args = parser.parse_args("") - # return args - return parser diff --git a/domainlab/algos/compos/matchdg_base.py b/domainlab/algos/compos/matchdg_base.py deleted file mode 100644 index 0df407375..000000000 --- a/domainlab/algos/compos/matchdg_base.py +++ /dev/null @@ -1,107 +0,0 @@ -import torch -from torch import optim -from domainlab.algos.compos.matchdg_match import MatchPair - - -class MatchAlgoBase(): - def __init__(self, task, phi, args, device, exp): - self.bs_match = args.bs # use the same batch size for match tensor - self.exp = exp - self.task = task - self.num_domain_tr = len(self.task.list_domain_tr) - train_domains = self.task.list_domain_tr - self.list_tr_domain_size = [len(self.task.dict_dset[key]) \ - for key in train_domains] - # so that order is kept! - self.base_domain_size = get_base_domain_size4match_dg(self.task) - self.dim_y = task.dim_y - - self.args = args - # @FIXME: training loader always drop the last batch, - # so inside matchdg, for the data storage tensor, - # loader is re-initialized by disabling drop - self.loader = task.loader_tr - self.device = device - self.phi = phi.to(self.device) - # - self.opt = self.get_opt_sgd() - self.scheduler = torch.optim.lr_scheduler.StepLR(self.opt, step_size=25) - self.ctr_mpath = self.exp.visitor.model_path + "_ctr" - # - self.tensor_ref_domain2each_domain_x = None - self.tensor_ref_domain2each_domain_y = None - - def init_erm_phase(self): - """ - loade model from disk after training - the ctr(contrastive learning) phase - """ - # the keys of :attr:`state_dict` must exactly match the - # keys returned by this module's - # :meth:`~torch.nn.Module.state_dict` function - self.phi.load_state_dict(torch.load(self.ctr_mpath), strict=False) - # load the phi network trained during the - # ctr(contrastive learning) phase - self.phi = self.phi.to(self.device) - # len((ctr_phi.state_dict()).keys()): 122, - # extra fields are fc.weight, fc.bias - self.phi.eval() # @FIXME - self.mk_match_tensor(epoch=0) - - def get_opt_sgd(self): - opt = optim.SGD([{'params': filter( - lambda p: p.requires_grad, - self.phi.parameters())}, ], - lr=self.args.lr, weight_decay=5e-4, - momentum=0.9, nesterov=True) - return opt - - def save_model_ctr_phase(self): - # Store the weights of the model - # dirname = os.path.dirname(self.ctr_mpath) - # Path(dirname).mkdir(parents=True, exist_ok=True) - torch.save(self.phi.state_dict(), self.ctr_mpath) - - def save_model_erm_phase(self): - torch.save(self.phi, self.exp.visitor.model_path) - - def mk_match_tensor(self, epoch): - """ - initialize or update match tensor - """ - obj_match = MatchPair(self.dim_y, - self.task.isize.i_c, - self.task.isize.i_h, - self.task.isize.i_w, - self.bs_match, - virtual_ref_dset_size=self.base_domain_size, - num_domains_tr=self.num_domain_tr, - list_tr_domain_size=self.list_tr_domain_size) - - # @FIXME: what is the usefulness of (epoch > 0) as argument - self.tensor_ref_domain2each_domain_x, self.tensor_ref_domain2each_domain_y = \ - obj_match(self.device, self.loader, self.phi, (epoch > 0)) - - -def get_base_domain_size4match_dg(task): - """ - Base domain is a dataset where each class - set come from one of the nominal domains - """ - # @FIXME: base domain should be calculated only on training domains - # instead of all the domains! - # domain_keys = task.get_list_domains() - domain_keys = task.list_domain_tr - base_domain_size = 0 - classes = task.list_str_y - for mclass in classes: - num = 0 - ref_domain = -1 - for _, domain_key in enumerate(domain_keys): - if task.dict_domain_class_count[domain_key][mclass] > num: - ref_domain = domain_key - num = task.dict_domain_class_count[domain_key][mclass] - print("for class ", mclass, " bigest sample size is ", - num, "ref domain is", ref_domain) - base_domain_size += num - return base_domain_size diff --git a/domainlab/algos/compos/matchdg_ctr_erm.py b/domainlab/algos/compos/matchdg_ctr_erm.py deleted file mode 100644 index 1a7ead13c..000000000 --- a/domainlab/algos/compos/matchdg_ctr_erm.py +++ /dev/null @@ -1,247 +0,0 @@ -import torch - -from domainlab.algos.compos.matchdg_base import MatchAlgoBase -from domainlab.algos.compos.matchdg_utils import (dist_cosine_agg, - dist_pairwise_cosine) - - -class MatchCtrErm(MatchAlgoBase): - """ - Contrastive Learning - """ - def __init__(self, task, phi, args, device, exp, flag_erm=False): - """ - """ - super().__init__(task, phi, args, device, exp) - self.epo_loss_tr = 0 - self.flag_erm = flag_erm - self.epos = self.args.epochs_ctr - self.epos_per_match = self.args.epos_per_match_update - self.str_phase = "ctr" - self.lambda_ctr = 1.0 - if self.flag_erm: - self.lambda_ctr = self.args.penalty_ws - self.epos = self.args.epochs_erm - self.str_phase = "erm" - self.init_erm_phase() - else: - self.mk_match_tensor(epoch=0) - - def train(self): - for epoch in range(self.epos): - self.tr_epoch(epoch) - - def tr_epoch(self, epoch): - """ - # data in one batch comes from two sources: one part from loader, - # the other part from match tensor - """ - self.epo_loss_tr = 0 - print(self.str_phase, "epoch", epoch) - # update match tensor - if (epoch + 1) % self.epos_per_match == 0: - self.mk_match_tensor(epoch) - - inds_shuffle = torch.randperm(self.tensor_ref_domain2each_domain_x.size(0)) - # NOTE: match tensor size: N(ref domain size) * #(train domains) * (image size: c*h*w) - # self.tensor_ref_domain2each_domain_x[inds_shuffle] shuffles the match tensor at the first dimension - tuple_tensor_refdomain2each = torch.split(self.tensor_ref_domain2each_domain_x[inds_shuffle], - self.args.bs, dim=0) - # Splits the tensor into chunks. Each chunk is a view of the original tensor of batch size self.args.bs - # return is a tuple of the splited chunks - tuple_tensor_ref_domain2each_y = torch.split(self.tensor_ref_domain2each_domain_y[inds_shuffle], - self.args.bs, dim=0) - print("number of batches in match tensor: ", len(tuple_tensor_refdomain2each)) - print("single batch match tensor size: ", tuple_tensor_refdomain2each[0].shape) - - for batch_idx, (x_e, y_e, d_e, *_) in enumerate(self.loader): - # random loader with same batch size as the match tensor loader - # the 4th output of self.loader is not used at all, - # is only used for creating the match tensor - self.opt.zero_grad() - x_e = x_e.to(self.device) # 64 * 1 * 224 * 224 - # y_e_scalar = torch.argmax(y_e, dim=1).to(self.device) - y_e = y_e.to(self.device) - # d_e = torch.argmax(d_e, dim=1).numpy() - d_e = d_e.to(self.device) - # for each batch, the list loss is re-initialized - - # CTR (contrastive) loss for CTR/ERM phase are different - list_batch_loss_ctr = [] - # for a single batch, loss need to be - # aggregated across different combinations of domains. - # Defining a leaf node can cause problem by loss_ctr += xxx, - # a list with python built-in "sum" can aggregate - # these losses within one batch - - if self.flag_erm: - # logit_yhat = self.phi(x_e) # @FIXME - # loss_erm_rnd_loader = F.cross_entropy(logit_yhat, y_e.long()).to(self.device) - loss_erm_rnd_loader = self.phi.cal_loss(x_e, y_e, d_e) - - num_batches = len(tuple_tensor_refdomain2each) - - if batch_idx >= num_batches: - print("ref/base domain vs each domain match \ - traversed one sweep, starting new epoch") - break - - curr_batch_size = tuple_tensor_refdomain2each[batch_idx].shape[0] - - batch_tensor_ref_domain2each = tuple_tensor_refdomain2each[batch_idx].to(self.device) - # make order 5 tensor: (ref_domain, domain, channel, img_h, img_w) - # with first dimension as batch size - - # clamp the first two dimensions so the phi network could map image to feature - batch_tensor_ref_domain2each = batch_tensor_ref_domain2each.view( - batch_tensor_ref_domain2each.shape[0]*batch_tensor_ref_domain2each.shape[1], - batch_tensor_ref_domain2each.shape[2], # channel - batch_tensor_ref_domain2each.shape[3], # img_h - batch_tensor_ref_domain2each.shape[4]) # img_w - # now batch_tensor_ref_domain2each first dim will not be batch_size! - # batch_tensor_ref_domain2each.shape torch.Size([40, channel, 224, 224]) - - # @FIXME: change to extract_feature? - batch_feat_ref_domain2each = self.phi(batch_tensor_ref_domain2each) - # batch_feat_ref_domain2each.shape torch.Size[40, 512] - # torch.sum(torch.isnan(batch_tensor_ref_domain2each)) - # assert not torch.sum(torch.isnan(batch_feat_ref_domain2each)) - flag_isnan = torch.any(torch.isnan(batch_feat_ref_domain2each)) - if flag_isnan: - # usually because learning rate is too big - raise RuntimeError("batch_feat_ref_domain2each NAN!") - - # for contrastive training phase, - # the last layer of the model is replaced with identity - - batch_ref_domain2each_y = tuple_tensor_ref_domain2each_y[batch_idx].to(self.device) - batch_ref_domain2each_y = batch_ref_domain2each_y.view(batch_ref_domain2each_y.shape[0]*batch_ref_domain2each_y.shape[1]) - - # @FIXME: - # self.phi.cal_loss(batch_tensor_ref_domain2each, - # batch_ref_domain2each_y) - - if self.flag_erm: - # loss_erm_match_tensor = F.cross_entropy(batch_feat_ref_domain2each, batch_ref_domain2each_y.long()).to(self.device) - # @FIXME: check if batch_ref_domain2each_y is - # continuous number which means it is at its initial value, - # not yet filled - # FIMXE: shall we leave batch_ref_domain2each_y scalar so it - # takes less memory? - loss_erm_match_tensor = self.phi.cal_loss(batch_tensor_ref_domain2each, batch_ref_domain2each_y.long()) - - # Creating tensor of shape (domain size, total domains, feat size ) - # The match tensor's first two dimension - # [(Ref domain size) * (# train domains)] - # has been clamped together to get features extracted - # through self.phi - - # it has to be reshaped into the match tensor shape, the same - # for the extracted feature here, it has to reshaped into - # the shape of the match tensor - # to make sure that the reshape only happens at the - # first two dimension, the feature dim has to be kept intact - dim_feat = batch_feat_ref_domain2each.shape[1] - batch_feat_ref_domain2each = batch_feat_ref_domain2each.view(curr_batch_size, self.num_domain_tr, dim_feat) - - batch_ref_domain2each_y = batch_ref_domain2each_y.view(curr_batch_size, self.num_domain_tr) - - # The match tensor's first two dimension - # [(Ref domain size) * (# train domains)] has been clamped - # together to get features extracted through self.phi - batch_tensor_ref_domain2each = \ - batch_tensor_ref_domain2each.view(curr_batch_size, - self.num_domain_tr, - batch_tensor_ref_domain2each.shape[1], # channel - batch_tensor_ref_domain2each.shape[2], # img_h - batch_tensor_ref_domain2each.shape[3]) # img_w - - # Contrastive Loss: class \times domain \times domain - counter_same_cls_diff_domain = 1 - for y_c in range(self.dim_y): - - subset_same_cls = (batch_ref_domain2each_y[:, 0] == y_c) - subset_diff_cls = (batch_ref_domain2each_y[:, 0] != y_c) - feat_same_cls = batch_feat_ref_domain2each[subset_same_cls] - feat_diff_cls = batch_feat_ref_domain2each[subset_diff_cls] - #print('class', y_c, "with same class and different class: ", - # feat_same_cls.shape[0], feat_diff_cls.shape[0]) - - if feat_same_cls.shape[0] == 0 or feat_diff_cls.shape[0] == 0: - # print("no instances of label", - # y_c, - # "in the current batch, continue") - continue - - if torch.sum(torch.isnan(feat_diff_cls)): - raise RuntimeError('feat_diff_cls has nan entrie(s)') - - feat_diff_cls = feat_diff_cls.view( - feat_diff_cls.shape[0]*feat_diff_cls.shape[1], - feat_diff_cls.shape[2]) - - for d_i in range(feat_same_cls.shape[1]): - dist_diff_cls_same_domain = dist_pairwise_cosine( - feat_same_cls[:, d_i, :], feat_diff_cls[:, :]) - - if torch.sum(torch.isnan(dist_diff_cls_same_domain)): - raise RuntimeError('dist_diff_cls_same_domain NAN') - - # iterate other domains - for d_j in range(feat_same_cls.shape[1]): - if d_i >= d_j: - continue - dist_same_cls_diff_domain = dist_cosine_agg(feat_same_cls[:, d_i, :], - feat_same_cls[:, d_j, :]) - - if torch.sum(torch.isnan(dist_same_cls_diff_domain)): - raise RuntimeError('dist_same_cls_diff_domain NAN') - - # CTR (contrastive) loss is exclusive for - # CTR phase and ERM phase - - if self.flag_erm: - list_batch_loss_ctr.append(torch.sum(dist_same_cls_diff_domain)) - else: - i_dist_same_cls_diff_domain = 1.0 - dist_same_cls_diff_domain - i_dist_same_cls_diff_domain = i_dist_same_cls_diff_domain / self.args.tau - partition = torch.log(torch.exp(i_dist_same_cls_diff_domain) + dist_diff_cls_same_domain) - list_batch_loss_ctr.append(-1 * torch.sum(i_dist_same_cls_diff_domain - partition)) - - counter_same_cls_diff_domain += dist_same_cls_diff_domain.shape[0] - - loss_ctr = sum(list_batch_loss_ctr) / counter_same_cls_diff_domain - - coeff = (epoch + 1)/(self.epos + 1) - # loss aggregation is over different domain - # combinations of the same batch - # https://discuss.pytorch.org/t/leaf-variable-was-used-in-an-inplace-operation/308 - # Loosely, tensors you create directly are leaf variables. - # Tensors that are the result of a differentiable operation are - # not leaf variables - - if self.flag_erm: - # extra loss of ERM phase: the ERM loss - # (the CTR loss for the ctr phase and erm phase are different) - # erm loss comes from two different data loaders, - # one is rnd (random) data loader - # the other one is the data loader from the match tensor - loss_e = torch.tensor(0.0, requires_grad=True) + \ - torch.mean(loss_erm_rnd_loader) + \ - torch.mean(loss_erm_match_tensor) + \ - self.lambda_ctr * coeff * loss_ctr - else: - loss_e = torch.tensor(0.0, requires_grad=True) + \ - self.lambda_ctr * coeff * loss_ctr - # @FIXME: without torch.tensor(0.0), after a few epochs, - # error "'float' object has no attribute 'backward'" - - loss_e.backward(retain_graph=False) - self.opt.step() - self.epo_loss_tr += loss_e.detach().item() - - torch.cuda.empty_cache() - - if not self.flag_erm: - # Save ctr model's weights post each epoch - self.save_model_ctr_phase() diff --git a/domainlab/algos/msels/a_model_sel.py b/domainlab/algos/msels/a_model_sel.py index c31ffab7c..e2e63c993 100644 --- a/domainlab/algos/msels/a_model_sel.py +++ b/domainlab/algos/msels/a_model_sel.py @@ -1,26 +1,103 @@ +""" +Abstract Model Selection +""" + import abc + class AMSel(metaclass=abc.ABCMeta): + """ + Abstract Model Selection + """ + def __init__(self): + """ + trainer and tr_observer + """ self.trainer = None - self.tr_obs = None + self._tr_obs = None + self.msel = None + self._max_es = None + + def reset(self): + """ + reset observer via reset model selector + """ + if self.msel is not None: + self.msel.reset() + + @property + def tr_obs(self): + """ + the observer from trainer + """ + return self._tr_obs + + @property + def max_es(self): + """ + maximum early stop + """ + if self._max_es is not None: + return self._max_es + if self.msel is not None: + return self.msel.max_es + return self._max_es def accept(self, trainer, tr_obs): """ Visitor pattern to trainer + accept trainer and tr_observer """ self.trainer = trainer - self.tr_obs = tr_obs + self._tr_obs = tr_obs + if self.msel is not None: + self.msel.accept(trainer, tr_obs) @abc.abstractmethod - def update(self): + def update(self, clear_counter=False): """ observer + visitor pattern to trainer + if the best model should be updated + return boolean """ - raise NotImplementedError def if_stop(self): """ check if trainer should stop + return boolean """ + # NOTE: since if_stop is not abstract, one has to + # be careful to always override it in child class + # only if the child class has a decorator which will + # dispatched. + if self.msel is not None: + return self.msel.if_stop() raise NotImplementedError + + @property + def best_val_acc(self): + """ + decoratee best val acc + """ + if self.msel is not None: + return self.msel.best_val_acc + return -1 + + @property + def best_te_metric(self): + """ + decoratee best test metric + """ + if self.msel is not None: + return self.msel.best_te_metric + return -1 + + @property + def sel_model_te_acc(self): + """ + the selected model test accuaracy + """ + if self.msel is not None: + return self.msel.sel_model_te_acc + return -1 diff --git a/domainlab/algos/msels/c_msel.py b/domainlab/algos/msels/c_msel.py deleted file mode 100644 index 815b34534..000000000 --- a/domainlab/algos/msels/c_msel.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Model Selection should be decoupled from -""" -from domainlab.algos.msels.a_model_sel import AMSel - - -class MSelTrLoss(AMSel): - """ - 1. Model selection using sum of loss across training domains - 2. Visitor pattern to trainer - """ - def __init__(self, max_es): - self.best_loss = float("inf") - self.es_c = 1 - self.max_es = max_es - super().__init__() - - def update(self): - """ - if the best model should be updated - """ - loss = self.trainer.epo_loss_tr # @FIXME - assert loss is not None - flag = True - if loss < self.best_loss: - self.es_c = 1 # restore counter - self.best_loss = loss - else: - self.es_c += 1 - print("early stop counter: ", self.es_c) - flag = False # do not update best model - return flag - - def if_stop(self): - """ - if should early stop - """ - return self.es_c > self.max_es diff --git a/domainlab/algos/msels/c_msel_oracle.py b/domainlab/algos/msels/c_msel_oracle.py index 9f3002e8f..e232b1e78 100644 --- a/domainlab/algos/msels/c_msel_oracle.py +++ b/domainlab/algos/msels/c_msel_oracle.py @@ -2,6 +2,7 @@ Model Selection should be decoupled from """ from domainlab.algos.msels.a_model_sel import AMSel +from domainlab.utils.logger import Logger class MSelOracleVisitor(AMSel): @@ -9,7 +10,8 @@ class MSelOracleVisitor(AMSel): save best out-of-domain test acc model, but do not affect how the final model is selected """ - def __init__(self, msel): + + def __init__(self, msel=None): """ Decorator pattern """ @@ -17,16 +19,38 @@ def __init__(self, msel): self.best_oracle_acc = 0 self.msel = msel - def update(self): + @property + def oracle_last_setpoint_sel_te_acc(self): + """ + last setpoint acc + """ + if self.msel is not None and hasattr( + self.msel, "oracle_last_setpoint_sel_te_acc" + ): + return self.msel.oracle_last_setpoint_sel_te_acc + return -1 + + def update(self, clear_counter=False): """ if the best model should be updated """ - self.tr_obs.exp.visitor.save(self.trainer.model, "epoch") - if self.tr_obs.metric_te["acc"] > self.best_oracle_acc: - self.best_oracle_acc = self.tr_obs.metric_te["acc"] # FIXME: only works for classification - self.tr_obs.exp.visitor.save(self.trainer.model, "oracle") - print("oracle model saved") - return self.msel.update() + self.trainer.model.save("epoch") + flag = False + if self.tr_obs.metric_val is None: + return super().update(clear_counter) + metric = self.tr_obs.metric_te[self.tr_obs.str_metric4msel] + if metric > self.best_oracle_acc: + self.best_oracle_acc = metric + if self.msel is not None: + self.trainer.model.save("oracle") + else: + self.trainer.model.save() + logger = Logger.get_logger() + logger.info("new oracle model saved") + flag = True + if self.msel is not None: + return self.msel.update(clear_counter) + return flag def if_stop(self): """ @@ -34,8 +58,11 @@ def if_stop(self): oracle model selection does not intervene how models get selected by the innermost model selection """ - return self.msel.if_stop() + if self.msel is not None: + return self.msel.if_stop() + return False def accept(self, trainer, tr_obs): - self.msel.accept(trainer, tr_obs) + if self.msel is not None: + self.msel.accept(trainer, tr_obs) super().accept(trainer, tr_obs) diff --git a/domainlab/algos/msels/c_msel_tr_loss.py b/domainlab/algos/msels/c_msel_tr_loss.py new file mode 100644 index 000000000..7ed3f1168 --- /dev/null +++ b/domainlab/algos/msels/c_msel_tr_loss.py @@ -0,0 +1,57 @@ +""" +Model Selection should be decoupled from +""" +import math + +from domainlab.algos.msels.a_model_sel import AMSel +from domainlab.utils.logger import Logger + + +class MSelTrLoss(AMSel): + """ + 1. Model selection using sum of loss across training domains + 2. Visitor pattern to trainer + """ + + def __init__(self, max_es): + super().__init__() + # NOTE: super() must come first otherwise it will overwrite existing + # values! + self.reset() + self._max_es = max_es + + def reset(self): + self.best_loss = float("inf") + self.es_c = 0 + + @property + def max_es(self): + return self._max_es + + def update(self, clear_counter=False): + """ + if the best model should be updated + """ + loss = self.trainer.epo_loss_tr # @FIXME + assert loss is not None + assert not math.isnan(loss) + flag = True + if loss < self.best_loss: + self.es_c = 0 # restore counter + self.best_loss = loss + else: + self.es_c += 1 + logger = Logger.get_logger() + logger.info(f"early stop counter: {self.es_c}") + logger.info(f"loss:{loss}, best loss: {self.best_loss}") + flag = False # do not update best model + if clear_counter: + logger.info("clearing counter") + self.es_c = 0 + return flag + + def if_stop(self): + """ + if should early stop + """ + return self.es_c >= self.max_es diff --git a/domainlab/algos/msels/c_msel_val.py b/domainlab/algos/msels/c_msel_val.py new file mode 100644 index 000000000..c1f2f5561 --- /dev/null +++ b/domainlab/algos/msels/c_msel_val.py @@ -0,0 +1,77 @@ +""" +Model Selection should be decoupled from +""" +from domainlab.algos.msels.c_msel_tr_loss import MSelTrLoss +from domainlab.utils.logger import Logger + + +class MSelValPerf(MSelTrLoss): + """ + 1. Model selection using validation performance + 2. Visitor pattern to trainer + """ + + def __init__(self, max_es): + super().__init__(max_es) # construct self.tr_obs (observer) + self.reset() + + def reset(self): + super().reset() + self._best_val_acc = 0.0 + self._sel_model_te_acc = 0.0 + self._best_te_metric = 0.0 + + @property + def sel_model_te_acc(self): + return self._sel_model_te_acc + + @property + def best_val_acc(self): + """ + decoratee best val acc + """ + return self._best_val_acc + + @property + def best_te_metric(self): + """ + decoratee best test metric + """ + return self._best_te_metric + + def update(self, clear_counter=False): + """ + if the best model should be updated + """ + flag = True + if self.tr_obs.metric_val is None: + return super().update(clear_counter) + metric = self.tr_obs.metric_val[self.tr_obs.str_metric4msel] + if self.tr_obs.metric_te is not None: + metric_te_current = self.tr_obs.metric_te[self.tr_obs.str_metric4msel] + self._best_te_metric = max(self._best_te_metric, metric_te_current) + + if metric > self._best_val_acc: # update hat{model} + # different from loss, accuracy should be improved: + # the bigger the better + self._best_val_acc = metric + self.es_c = 0 # restore counter + if self.tr_obs.metric_te is not None: + metric_te_current = self.tr_obs.metric_te[self.tr_obs.str_metric4msel] + self._sel_model_te_acc = metric_te_current + + else: + self.es_c += 1 + logger = Logger.get_logger() + logger.info(f"early stop counter: {self.es_c}") + logger.info( + f"val acc:{self.tr_obs.metric_val['acc']}, " + + f"best validation acc: {self.best_val_acc}, " + + f"corresponding to test acc: \ + {self.sel_model_te_acc} / {self.best_te_metric}" + ) + flag = False # do not update best model + if clear_counter: + logger.info("clearing counter") + self.es_c = 0 + return flag diff --git a/domainlab/algos/observers/a_observer.py b/domainlab/algos/observers/a_observer.py index 9451897cd..bdad57360 100644 --- a/domainlab/algos/observers/a_observer.py +++ b/domainlab/algos/observers/a_observer.py @@ -8,8 +8,33 @@ class AObVisitor(metaclass=abc.ABCMeta): """ Observer + Visitor pattern for model selection """ + + def __init__(self): + self.task = None + self.device = None + self.epo_te = None + self.str_msel = None + self.keep_model = None + self.loader_te = None + self.loader_tr = None + self.loader_val = None + + def set_task(self, task, args, device): + """ + couple observer with task + """ + self.task = task + self.device = device + self.epo_te = args.epo_te + self.str_msel = args.msel # FIXME: consistent with self.model_sel? + self.keep_model = args.keep_model + self.loader_te = self.task.loader_te + self.loader_tr = self.task.loader_tr + # Note loader_tr behaves/inherit different properties than loader_te + self.loader_val = self.task.loader_val + @abc.abstractmethod - def update(self, epoch): + def update(self, epoch) -> bool: """ return True/False whether the trainer should stop training """ @@ -31,3 +56,9 @@ def clean_up(self): """ to be called by a decorator """ + + def reset(self): + """ + reset observer via reset model selector + """ + self.model_sel.reset() diff --git a/domainlab/algos/observers/b_obvisitor.py b/domainlab/algos/observers/b_obvisitor.py index acaf00811..04231a917 100644 --- a/domainlab/algos/observers/b_obvisitor.py +++ b/domainlab/algos/observers/b_obvisitor.py @@ -1,95 +1,157 @@ +""" +observer and visitor pattern, responsible train, validation, test +dispatch performance evaluation to model, +dispatch model selection to model selection object +""" import os -import warnings - from domainlab.algos.observers.a_observer import AObVisitor from domainlab.tasks.task_folder_mk import NodeTaskFolderClassNaMismatch from domainlab.tasks.task_pathlist import NodeTaskPathListDummy +from domainlab.utils.logger import Logger class ObVisitor(AObVisitor): """ Observer + Visitor pattern for model selection """ - def __init__(self, exp, model_sel, device): + + def __init__(self, model_sel): """ observer trainer """ + super().__init__() self.host_trainer = None - self.exp = exp self.model_sel = model_sel - self.device = device - self.task = self.exp.task - self.loader_te = self.exp.task.loader_te - self.loader_tr = self.exp.task.loader_tr - self.loader_val = self.exp.task.loader_val - # Note loader_tr behaves/inherit different properties than loader_te - self.epo_te = self.exp.args.epo_te self.epo = None self.metric_te = None - self.keep_model = self.exp.args.keep_model + self.metric_val = None self.perf_metric = None + @property + def str_metric4msel(self): + """ + string representing the metric used for persisting models on the disk + """ + return self.host_trainer.str_metric4msel + def update(self, epoch): - print("epoch:", epoch) + logger = Logger.get_logger() + logger.info(f"epoch: {epoch}") self.epo = epoch if epoch % self.epo_te == 0: - metric_te = self.host_trainer.model.cal_perf_metric( - self.loader_tr, self.device, self.loader_te) - self.metric_te = metric_te + logger.info("---- Training Domain: ") + self.host_trainer.model.cal_perf_metric(self.loader_tr, self.device) + if self.loader_val is not None: + logger.info("---- Validation: ") + self.metric_val = self.host_trainer.model.cal_perf_metric( + self.loader_val, self.device + ) + if self.loader_te is not None: + logger.info("---- Test Domain (oracle): ") + metric_te = self.host_trainer.model.cal_perf_metric( + self.loader_te, self.device + ) + self.metric_te = metric_te if self.model_sel.update(): - print("model selected") - self.exp.visitor.save(self.host_trainer.model) - print("persisted") - return self.model_sel.if_stop() + logger.info("better model found") + self.host_trainer.model.save() + logger.info("persisted") + flag_stop = self.model_sel.if_stop() + flag_enough = epoch >= self.host_trainer.aconf.epos_min + return flag_stop & flag_enough def accept(self, trainer): """ accept invitation as a visitor """ self.host_trainer = trainer - self.perf_metric = self.host_trainer.model.create_perf_obj(self.task) self.model_sel.accept(trainer, self) + self.set_task(trainer.task, args=trainer.aconf, device=trainer.device) + self.perf_metric = self.host_trainer.model.create_perf_obj(self.task) def after_all(self): """ After training is done """ - self.exp.visitor.save(self.host_trainer.model, "final") - model_ld = self.exp.visitor.load() + model_ld = None + try: + model_ld = self.host_trainer.model.load() + except FileNotFoundError as err: + # if other errors/exceptions occur, we do not catch them + # other exceptions will terminate the python script + # this can happen if loss is increasing, model never get selected + logger = Logger.get_logger() + logger.warning(err) + logger.warning( + "this error can occur if model selection criteria \ + is worsening, " + "model never get persisted, \ + no performance metric is reported" + ) + return model_ld = model_ld.to(self.device) model_ld.eval() - print("persisted model performance metric: \n") - metric_te = model_ld.cal_perf_metric(self.loader_tr, self.device, self.loader_te) - self.exp.visitor(metric_te) - flag_task_folder = isinstance(self.exp.task, NodeTaskFolderClassNaMismatch) - flag_task_path_list = isinstance(self.exp.task, NodeTaskPathListDummy) + logger = Logger.get_logger() + logger.info("persisted model performance metric: \n") + metric_te = model_ld.cal_perf_metric(self.loader_te, self.device) + dict_2add = self.cal_oracle_perf() + if dict_2add is not None: + metric_te.update(dict_2add) + else: + metric_te.update({"acc_oracle": -1}) + if hasattr(self, "model_sel"): + metric_te.update({"acc_val": self.model_sel.best_val_acc}) + else: + metric_te.update({"acc_val": -1}) + self.dump_prediction(model_ld, metric_te) + # save metric to one line in csv result file + self.host_trainer.model.visitor(metric_te) + # prediction dump of test domain is essential + # to verify the prediction results + + def cal_oracle_perf(self): + """ + calculate oracle performance + """ + try: + model_or = self.host_trainer.model.load("oracle") + # @FIXME: name "oracle is a strong dependency + model_or = model_or.to(self.device) + model_or.eval() + except FileNotFoundError: + return {"acc_oracle": -1} + logger = Logger.get_logger() + logger.info("oracle model performance metric: \n") + metric_te = model_or.cal_perf_metric(self.loader_te, self.device) + return {"acc_oracle": metric_te["acc"]} + + def dump_prediction(self, model_ld, metric_te): + """ + given the test domain loader, use the loaded model \ + model_ld to predict each instance + """ + flag_task_folder = isinstance( + self.host_trainer.task, NodeTaskFolderClassNaMismatch + ) + flag_task_path_list = isinstance(self.host_trainer.task, NodeTaskPathListDummy) if flag_task_folder or flag_task_path_list: - fname4model = self.exp.visitor.model_path # pylint: disable=E1101 - file_prefix = os.path.splitext(fname4model)[0] # remove ".csv" + fname4model = ( + self.host_trainer.model.visitor.model_path + ) # pylint: disable=E1101 + file_prefix = os.path.splitext(fname4model)[0] # remove ".model" + dir4preds = os.path.join(self.host_trainer.aconf.out, "saved_predicts") + if not os.path.exists(dir4preds): + os.mkdir(dir4preds) + file_prefix = os.path.join(dir4preds, os.path.basename(file_prefix)) file_name = file_prefix + "_instance_wise_predictions.txt" - self.host_trainer.model.pred2file( - self.loader_te, self.device, - filename=file_name) + model_ld.pred2file( + self.loader_te, self.device, filename=file_name, metric_te=metric_te + ) def clean_up(self): """ to be called by a decorator """ if not self.keep_model: - try: - # oracle means use out-of-domain - # test accuracy to select the model - self.exp.visitor.remove("oracle") # pylint: disable=E1101 - # the last epoch - self.exp.visitor.remove("epoch") # pylint: disable=E1101 - # epoch exist to still have a model to evaluate - # if the training stops in between - self.exp.visitor.remove("final") # pylint: disable=E1101 - self.exp.visitor.remove() # pylint: disable=E1101 - except FileNotFoundError: - warnings.warn("failed to remove model") - try: - self.exp.visitor.remove("ctr") # pylint: disable=E1101 For matchdg - except FileNotFoundError: - pass + self.host_trainer.model.visitor.clean_up() diff --git a/domainlab/algos/observers/c_obvisitor_cleanup.py b/domainlab/algos/observers/c_obvisitor_cleanup.py index f31aedfac..91ac53216 100644 --- a/domainlab/algos/observers/c_obvisitor_cleanup.py +++ b/domainlab/algos/observers/c_obvisitor_cleanup.py @@ -3,9 +3,11 @@ class ObVisitorCleanUp(AObVisitor): """ - decorator of observer + decorator of observer, instead of using if and else to decide clean up or not, we use decorator """ + def __init__(self, observer): + super().__init__() self.observer = observer def after_all(self): @@ -16,7 +18,11 @@ def accept(self, trainer): self.observer.accept(trainer) def update(self, epoch): - self.observer.update(epoch) + return self.observer.update(epoch) def clean_up(self): self.observer.clean_up() + + @property + def model_sel(self): + return self.observer.model_sel diff --git a/domainlab/algos/observers/c_obvisitor_gen.py b/domainlab/algos/observers/c_obvisitor_gen.py index a4eccb369..45571b1b2 100644 --- a/domainlab/algos/observers/c_obvisitor_gen.py +++ b/domainlab/algos/observers/c_obvisitor_gen.py @@ -1,26 +1,46 @@ from domainlab.algos.observers.b_obvisitor import ObVisitor from domainlab.utils.flows_gen_img_model import fun_gen +from domainlab.utils.logger import Logger class ObVisitorGen(ObVisitor): """ For Generative Models """ + def after_all(self): super().after_all() - print("generating images for final model at last epoch") - fun_gen(subfolder_na=self.exp.visitor.model_name+"final", - args=self.exp.args, node=self.exp.task, model=self.host_trainer.model, device=self.device) + logger = Logger.get_logger() + logger.info("generating images for final model at last epoch") + fun_gen( + subfolder_na=self.host_trainer.model.visitor.model_name + "final", + args=self.host_trainer.aconf, + node=self.host_trainer.task, + model=self.host_trainer.model, + device=self.device, + ) - print("generating images for oracle model") - model_or = self.exp.visitor.load("oracle") # @FIXME: name "oracle is a strong dependency + logger.info("generating images for oracle model") + model_or = self.host_trainer.model.load( + "oracle" + ) # @FIXME: name "oracle is a strong dependency model_or = model_or.to(self.device) model_or.eval() - fun_gen(subfolder_na=self.exp.visitor.model_name+"oracle", - args=self.exp.args, node=self.exp.task, model=model_or, device=self.device) - print("generating images for selected model") - model_ld = self.exp.visitor.load() + fun_gen( + subfolder_na=self.host_trainer.model.visitor.model_name + "oracle", + args=self.host_trainer.aconf, + node=self.host_trainer.task, + model=model_or, + device=self.device, + ) + logger.info("generating images for selected model") + model_ld = self.host_trainer.model.load() model_ld = model_ld.to(self.device) model_ld.eval() - fun_gen(subfolder_na=self.exp.visitor.model_name+"selected", - args=self.exp.args, node=self.exp.task, model=model_ld, device=self.device) + fun_gen( + subfolder_na=self.host_trainer.model.visitor.model_name + "selected", + args=self.host_trainer.aconf, + node=self.host_trainer.task, + model=model_ld, + device=self.device, + ) diff --git a/domainlab/algos/trainers/a_trainer.py b/domainlab/algos/trainers/a_trainer.py index 322d8c2e9..9bc126705 100644 --- a/domainlab/algos/trainers/a_trainer.py +++ b/domainlab/algos/trainers/a_trainer.py @@ -3,25 +3,145 @@ """ import abc +from torch import optim -class AbstractTrainer(metaclass=abc.ABCMeta): +from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler + + +def mk_opt(model, aconf): + """ + create optimizer + """ + if model._decoratee is None: + optimizer = optim.Adam(model.parameters(), lr=aconf.lr) + else: + var1 = model.parameters() + var2 = model._decoratee.parameters() + set_param = set(list(var1) + list(var2)) + list_par = list(set_param) + # optimizer = optim.Adam([var1, var2], lr=aconf.lr) + # optimizer = optim.Adam([ + # {'params': model.parameters()}, + # {'params': model._decoratee.parameters()} + # ], lr=aconf.lr) + optimizer = optim.Adam(list_par, lr=aconf.lr) + return optimizer + + +class AbstractTrainer(AbstractChainNodeHandler, metaclass=abc.ABCMeta): """ Algorithm director that controls the data flow """ - def __init__(self, model, task, observer, device, aconf): + + @property + def p_na_prefix(self): + """ + common prefix for Trainers + """ + return "Trainer" + + def extend(self, trainer): + """ + extend current trainer with another trainer + """ + self._decoratee = trainer + + def __init__(self, successor_node=None, extend=None): + """__init__. + :param successor_node: + """ + super().__init__(successor_node) + self._model = None + self._decoratee = extend + self.task = None + self.observer = None + self.device = None + self.aconf = None + # + self.dict_loader_tr = None + self.loader_tr = None + self.loader_te = None + self.num_batches = None + self.flag_update_hyper_per_epoch = None + self.flag_update_hyper_per_batch = None + self.epo_loss_tr = None + self.epo_reg_loss_tr = None + self.epo_task_loss_tr = None + self.counter_batch = None + self.hyper_scheduler = None + self.optimizer = None + self.exp = None + # matchdg + self.lambda_ctr = None + self.flag_stop = None + self.flag_erm = None + self.tensor_ref_domain2each_domain_x = None + self.tensor_ref_domain2each_domain_y = None + self.base_domain_size = None + self.tuple_tensor_ref_domain2each_y = None + self.tuple_tensor_refdomain2each = None + # mldg + self.inner_trainer = None + self.loader_tr_source_target = None + self.flag_initialized = False + + @property + def model(self): + """ + property model, which can be another trainer or model + """ + return self.get_model() + + @model.setter + def model(self, model): + self._model = model + + @property + def str_metric4msel(self): + """ + metric for model selection + """ + return self.model.metric4msel + + @property + def list_tr_domain_size(self): + """ + get a list of training domain size + """ + train_domains = self.task.list_domain_tr + return [len(self.task.dict_dset_tr[key]) for key in train_domains] + + @property + def decoratee(self): + if self._decoratee is None: + return self.model + return self._decoratee + + def init_business(self, model, task, observer, device, aconf, flag_accept=True): """ model, task, observer, device, aconf """ - # @FIXME: aconf and args should be separated + # Note self.decoratee can be both model and trainer, + # but self._decoratee can only be trainer! + if self._decoratee is not None: + self._decoratee.init_business( + model, task, observer, device, aconf, flag_accept + ) self.model = model self.task = task + self.task.init_business(trainer=self, args=aconf) + self.model.list_d_tr = self.task.list_domain_tr self.observer = observer self.device = device self.aconf = aconf # + self.dict_loader_tr = task.dict_loader_tr self.loader_tr = task.loader_tr self.loader_te = task.loader_te - self.observer.accept(self) + + if flag_accept: + self.observer.accept(self) + self.model = self.model.to(device) # self.num_batches = len(self.loader_tr) @@ -29,13 +149,27 @@ def __init__(self, model, task, observer, device, aconf): self.flag_update_hyper_per_batch = False self.epo_loss_tr = None self.hyper_scheduler = None + self.reset() + self.flag_initialized = True + + def reset(self): + """ + make a new optimizer to clear internal state + """ + self.optimizer = mk_opt(self.model, self.aconf) @abc.abstractmethod def tr_epoch(self, epoch): """ :param epoch: """ - raise NotImplementedError + + def before_batch(self, epoch, ind_batch): + """ + :param epoch: + :param ind_batch: + """ + return def after_batch(self, epoch, ind_batch): """ @@ -49,10 +183,76 @@ def before_tr(self): """ before training, probe model performance """ - raise NotImplementedError def post_tr(self): """ after training """ self.observer.after_all() + + @property + def name(self): + """ + get the name of the algorithm + """ + na_prefix = self.p_na_prefix + len_prefix = len(na_prefix) + na_class = type(self).__name__ + if na_class[:len_prefix] != na_prefix: + raise RuntimeError( + "Trainer builder node class must start with ", + na_prefix, + "the current class is named: ", + na_class, + ) + return type(self).__name__[len_prefix:].lower() + + def is_myjob(self, request): + """ + :param request: string + """ + return request == self.name + + def get_model(self): + """ + recursively get the "real" model from trainer + """ + if "trainer" not in str(type(self._model)).lower(): + return self._model + return self._model.get_model() + + def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): + """ + decorate trainer regularization loss + combine losses of current trainer with self._model.cal_reg_loss, which + can be either a trainer or a model + """ + list_reg_model, list_mu_model = self.decoratee.cal_reg_loss( + tensor_x, tensor_y, tensor_d, others + ) + assert len(list_reg_model) == len(list_mu_model) + + list_reg_trainer, list_mu_trainer = self._cal_reg_loss( + tensor_x, tensor_y, tensor_d, others + ) + assert len(list_reg_trainer) == len(list_mu_trainer) + + list_loss = list_reg_model + list_reg_trainer + list_mu = list_mu_model + list_mu_trainer + return list_loss, list_mu + + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): + """ + interface for each trainer to implement + """ + return [], [] + + def dset_decoration_args_algo(self, args, ddset): + """ + decorate dataset to get extra entries in load item, for instance, + jigen need permutation index + this parent class function delegate decoration to its decoratee + """ + if self._decoratee is not None: + return self._decoratee.dset_decoration_args_algo(args, ddset) + return ddset diff --git a/domainlab/algos/trainers/args_dial.py b/domainlab/algos/trainers/args_dial.py index 118715f35..0c0445915 100644 --- a/domainlab/algos/trainers/args_dial.py +++ b/domainlab/algos/trainers/args_dial.py @@ -7,12 +7,28 @@ def add_args2parser_dial(parser): """ append hyper-parameters to the main argparser """ - parser.add_argument('--dial_steps_perturb', type=int, default=3, - help='how many gradient step to go to find an image as adversarials') - parser.add_argument('--dial_noise_scale', type=float, default=0.001, - help='variance of gaussian noise to inject on pure image') - parser.add_argument('--dial_lr', type=float, default=0.003, - help='learning rate to generate adversarial images') - parser.add_argument('--dial_epsilon', type=float, default=0.031, - help='pixel wise threshold to perturb images') + parser.add_argument( + "--dial_steps_perturb", + type=int, + default=3, + help="how many gradient step to go to find an image as adversarials", + ) + parser.add_argument( + "--dial_noise_scale", + type=float, + default=0.001, + help="variance of gaussian noise to inject on pure image", + ) + parser.add_argument( + "--dial_lr", + type=float, + default=0.003, + help="learning rate to generate adversarial images", + ) + parser.add_argument( + "--dial_epsilon", + type=float, + default=0.031, + help="pixel wise threshold to perturb images", + ) return parser diff --git a/domainlab/algos/compos/__init__.py b/domainlab/algos/trainers/compos/__init__.py similarity index 100% rename from domainlab/algos/compos/__init__.py rename to domainlab/algos/trainers/compos/__init__.py diff --git a/domainlab/algos/trainers/compos/matchdg_args.py b/domainlab/algos/trainers/compos/matchdg_args.py new file mode 100644 index 000000000..ce649ac0e --- /dev/null +++ b/domainlab/algos/trainers/compos/matchdg_args.py @@ -0,0 +1,25 @@ +""" +args for matchdg +""" + + +def add_args2parser_matchdg(parser): + """ + args for matchdg + """ + # parser = argparse.ArgumentParser() + parser.add_argument( + "--tau", type=float, default=0.05, help="factor to magnify cosine similarity" + ) + parser.add_argument( + "--epos_per_match_update", + type=int, + default=5, + help="Number of epochs before updating the match tensor", + ) + parser.add_argument( + "--epochs_ctr", type=int, default=1, help="Total number of epochs for ctr" + ) + # args = parser.parse_args("") + # return args + return parser diff --git a/domainlab/algos/compos/matchdg_match.py b/domainlab/algos/trainers/compos/matchdg_match.py similarity index 56% rename from domainlab/algos/compos/matchdg_match.py rename to domainlab/algos/trainers/compos/matchdg_match.py index f6f8c71ae..78e67abde 100644 --- a/domainlab/algos/compos/matchdg_match.py +++ b/domainlab/algos/trainers/compos/matchdg_match.py @@ -3,39 +3,57 @@ import numpy as np import torch -from domainlab.algos.compos.matchdg_utils import ( - MatchDictNumDomain2SizeDomain, MatchDictVirtualRefDset2EachDomain) +from domainlab.algos.trainers.compos.matchdg_utils import ( + MatchDictNumDomain2SizeDomain, + MatchDictVirtualRefDset2EachDomain, +) from domainlab.tasks.utils_task import mk_loader +from domainlab.utils.logger import Logger from domainlab.utils.utils_class import store_args -class MatchPair(): +class MatchPair: + """ + match different input + """ @store_args - def __init__(self, - dim_y, # @TODO: dim_y is not used here - i_c, - i_h, - i_w, - bs_match, # @TODO: bs_match is not used here - virtual_ref_dset_size, - num_domains_tr, - list_tr_domain_size): + def __init__( + self, + dim_y, + i_c, + i_h, + i_w, + bs_match, + virtual_ref_dset_size, + num_domains_tr, + list_tr_domain_size, + ): """ :param virtual_ref_dset_size: sum of biggest class sizes :param num_domains_tr: :param list_tr_domain_size: - :param phi: neural network to generate causal features from input """ + self.dim_y = dim_y + self.bs_match = bs_match + self.virtual_ref_dset_size = virtual_ref_dset_size + self.num_domains_tr = num_domains_tr + self.list_tr_domain_size = list_tr_domain_size self.dict_cls_ind_base_domain_ind = {} self.dict_virtual_dset2each_domain = MatchDictVirtualRefDset2EachDomain( virtual_ref_dset_size=virtual_ref_dset_size, num_domains_tr=num_domains_tr, - i_c=i_c, i_h=i_h, i_w=i_w)() + i_c=i_c, + i_h=i_h, + i_w=i_w, + )() self.dict_domain_data = MatchDictNumDomain2SizeDomain( num_domains_tr=num_domains_tr, list_tr_domain_size=list_tr_domain_size, - i_c=i_c, i_h=i_h, i_w=i_w)() + i_c=i_c, + i_h=i_h, + i_w=i_w, + )() self.indices_matched = {} for key in range(virtual_ref_dset_size): @@ -54,14 +72,12 @@ def _fill_data(self, loader): # NOTE: loader contains data from several dataset list_idx_several_ds = [] loader_full_data = mk_loader( - loader.dataset, - bsize=loader.batch_size, - drop_last=False) + loader.dataset, bsize=loader.batch_size, drop_last=False + ) # @FIXME: training loader will always drop the last incomplete batch for _, (x_e, y_e, d_e, idx_e) in enumerate(loader_full_data): # traverse mixed domain data from loader list_idx_several_ds.extend(list(idx_e.cpu().numpy())) - x_e = x_e y_e = torch.argmax(y_e, dim=1) d_e = torch.argmax(d_e, dim=1).numpy() @@ -69,7 +85,7 @@ def _fill_data(self, loader): unique_domains = np.unique(d_e) for domain_idx in unique_domains: # select all instances belong to one domain - flag_curr_domain = (d_e == domain_idx) + flag_curr_domain = d_e == domain_idx # flag_curr_domain is subset indicator of # True of False for selection of data from the mini-batch @@ -86,15 +102,18 @@ def _fill_data(self, loader): # tensor.item get the scalar global_ind = global_indices[local_ind].item() - self.dict_domain_data[domain_idx]['data'][global_ind] = \ - x_e[flag_curr_domain][local_ind] + self.dict_domain_data[domain_idx]["data"][global_ind] = x_e[ + flag_curr_domain + ][local_ind] # flag_curr_domain are subset indicator # for selection of domain - self.dict_domain_data[domain_idx]['label'][global_ind] = \ - y_e[flag_curr_domain][local_ind] + self.dict_domain_data[domain_idx]["label"][global_ind] = y_e[ + flag_curr_domain + ][local_ind] # copy trainining batch to dict_domain_data - self.dict_domain_data[domain_idx]['idx'][global_ind] = \ - idx_e[flag_curr_domain][local_ind] + self.dict_domain_data[domain_idx]["idx"][global_ind] = idx_e[ + flag_curr_domain + ][local_ind] self.domain_count[domain_idx] += 1 # if all data has been re-organized(filled) into the current tensor @@ -104,8 +123,9 @@ def _fill_data(self, loader): # value instead of class label for domain in range(self.num_domains_tr): if self.domain_count[domain] != self.list_tr_domain_size[domain]: - warnings.warn("domain_count show matching \ - dictionary missing data!") + logger = Logger.get_logger() + logger.warning("domain_count show matching: dictionary missing data!") + warnings.warn("domain_count show matching: dictionary missing data!") def _cal_base_domain(self): """ @@ -117,20 +137,27 @@ def _cal_base_domain(self): base_domain_size = 0 base_domain_idx = -1 for domain_idx in range(self.num_domains_tr): - flag_curr_class = (self.dict_domain_data[domain_idx]['label'] == y_c) # tensor of True/False - curr_size = self.dict_domain_data[domain_idx]['label'][flag_curr_class].shape[0] # flag_curr_class are subset indicator + flag_curr_class = ( + self.dict_domain_data[domain_idx]["label"] == y_c + ) # tensor of True/False + curr_size = self.dict_domain_data[domain_idx]["label"][ + flag_curr_class + ].shape[0] + # flag_curr_class are subset indicator if base_domain_size < curr_size: base_domain_size = curr_size base_domain_idx = domain_idx self.dict_cls_ind_base_domain_ind[y_c] = base_domain_idx # for each class label, there is a base domain - print("for class", y_c) - print("domain index as base domain:", base_domain_idx) - print("Base Domain size", base_domain_size) + logger = Logger.get_logger() + logger.info(f"for class {y_c}") + logger.info(f"domain index as base domain: {base_domain_idx}") + logger.info(f"Base Domain size {base_domain_size}") - - - def __call__(self, device, loader, phi, flag_match_min_dist): + def __call__(self, device, loader, fun_extract_semantic_feat, flag_match_min_dist): + """ + :param fun_extract_semantic_feat: function to generate causal features from input + """ self._fill_data(loader) self._cal_base_domain() for curr_domain_ind in range(self.num_domains_tr): @@ -140,64 +167,88 @@ def __call__(self, device, loader, phi, flag_match_min_dist): base_domain_idx = self.dict_cls_ind_base_domain_ind[y_c] # subset indicator - flags_base_domain_curr_cls = \ - (self.dict_domain_data[base_domain_idx]['label'] == y_c) + flags_base_domain_curr_cls = ( + self.dict_domain_data[base_domain_idx]["label"] == y_c + ) flags_base_domain_curr_cls = flags_base_domain_curr_cls[:, 0] - global_inds_base_domain_curr_cls = self.dict_domain_data[base_domain_idx]['idx'][flags_base_domain_curr_cls] + global_inds_base_domain_curr_cls = self.dict_domain_data[ + base_domain_idx + ]["idx"][flags_base_domain_curr_cls] # pick out base domain class label y_c images # the difference of this block is "curr_domain_ind" # in iteration is # used instead of base_domain_idx for current class # pick out current domain y_c class images - flag_curr_domain_curr_cls = (self.dict_domain_data[curr_domain_ind]['label'] == y_c) + flag_curr_domain_curr_cls = ( + self.dict_domain_data[curr_domain_ind]["label"] == y_c + ) # NO label matches y_c flag_curr_domain_curr_cls = flag_curr_domain_curr_cls[:, 0] - global_inds_curr_domain_curr_cls = self.dict_domain_data[curr_domain_ind]['idx'][flag_curr_domain_curr_cls] + global_inds_curr_domain_curr_cls = self.dict_domain_data[ + curr_domain_ind + ]["idx"][flag_curr_domain_curr_cls] size_curr_domain_curr_cls = global_inds_curr_domain_curr_cls.shape[0] - if size_curr_domain_curr_cls == 0: # there is no class y_c in current domain - print("current domain", - curr_domain_ind, - " does not contain class ", y_c) - raise RuntimeError("current domain does not contain all classes") + if ( + size_curr_domain_curr_cls == 0 + ): # there is no class y_c in current domain + raise RuntimeError( + f"current domain {curr_domain_ind} does not contain class {y_c}" + ) # compute base domain features for class label y_c - x_base_domain_curr_cls = self.dict_domain_data[base_domain_idx]['data'][flags_base_domain_curr_cls] + x_base_domain_curr_cls = self.dict_domain_data[base_domain_idx]["data"][ + flags_base_domain_curr_cls + ] # pick out base domain class label y_c images # split data into chunks - tuple_batch_x_base_domain_curr_cls = torch.split(x_base_domain_curr_cls, self.bs_match, dim=0) + tuple_batch_x_base_domain_curr_cls = torch.split( + x_base_domain_curr_cls, self.bs_match, dim=0 + ) # @FIXME. when x_base_domain_curr_cls is smaller # than the self.bs_match, then there is only one batch list_base_feat = [] for batch_x_base_domain_curr_cls in tuple_batch_x_base_domain_curr_cls: with torch.no_grad(): - batch_x_base_domain_curr_cls = batch_x_base_domain_curr_cls.to(device) - feat = phi(batch_x_base_domain_curr_cls) + batch_x_base_domain_curr_cls = batch_x_base_domain_curr_cls.to( + device + ) + feat = fun_extract_semantic_feat(batch_x_base_domain_curr_cls) list_base_feat.append(feat.cpu()) - tensor_feat_base_domain_curr_cls = torch.cat(list_base_feat) # base domain features + tensor_feat_base_domain_curr_cls = torch.cat(list_base_feat) + # base domain features if flag_match_min_dist: # if epoch > 0:flag_match_min_dist=True - x_curr_domain_curr_cls = self.dict_domain_data[curr_domain_ind]['data'][flag_curr_domain_curr_cls] + x_curr_domain_curr_cls = self.dict_domain_data[curr_domain_ind][ + "data" + ][flag_curr_domain_curr_cls] # indices_curr pick out current domain y_c class images - tuple_x_batch_curr_domain_curr_cls = torch.split(x_curr_domain_curr_cls, self.bs_match, dim=0) + tuple_x_batch_curr_domain_curr_cls = torch.split( + x_curr_domain_curr_cls, self.bs_match, dim=0 + ) list_feat_x_curr_domain_curr_cls = [] for batch_feat in tuple_x_batch_curr_domain_curr_cls: with torch.no_grad(): batch_feat = batch_feat.to(device) - out = phi(batch_feat) + out = fun_extract_semantic_feat(batch_feat) list_feat_x_curr_domain_curr_cls.append(out.cpu()) - tensor_feat_curr_domain_curr_cls = torch.cat(list_feat_x_curr_domain_curr_cls) + tensor_feat_curr_domain_curr_cls = torch.cat( + list_feat_x_curr_domain_curr_cls + ) # feature through inference network for the current domain of class y_c - tensor_feat_base_domain_curr_cls = tensor_feat_base_domain_curr_cls.unsqueeze(1) - tuple_feat_base_domain_curr_cls = torch.split(tensor_feat_base_domain_curr_cls, self.bs_match, dim=0) + tensor_feat_base_domain_curr_cls = ( + tensor_feat_base_domain_curr_cls.unsqueeze(1) + ) + tuple_feat_base_domain_curr_cls = torch.split( + tensor_feat_base_domain_curr_cls, self.bs_match, dim=0 + ) counter_curr_cls_base_domain = 0 # tuple_feat_base_domain_curr_cls is a tuple of splitted part for feat_base_domain_curr_cls in tuple_feat_base_domain_curr_cls: - - if flag_match_min_dist: # if epoch > 0:flag_match_min_dist=True + if flag_match_min_dist: # if epoch > 0:flag_match_min_dist=True # Need to compute over batches of # feature due to device Memory out errors # Else no need for loop over @@ -205,15 +256,26 @@ def __call__(self, device, loader, phi, flag_match_min_dist): # could have simply computed # tensor_feat_curr_domain_curr_cls - # tensor_feat_base_domain_curr_cls - dist_same_class_base_domain_curr_domain = torch.sum((tensor_feat_curr_domain_curr_cls - feat_base_domain_curr_cls)**2, dim=2) + dist_same_class_base_domain_curr_domain = torch.sum( + ( + tensor_feat_curr_domain_curr_cls + - feat_base_domain_curr_cls + ) + ** 2, + dim=2, + ) # tensor_feat_curr_domain_curr_cls.shape torch.Size([184, 512]) # feat_base_domain_curr_cls.shape torch.Size([64, 1, 512]) - # (tensor_feat_curr_domain_curr_cls - feat_base_domain_curr_cls).shape: torch.Size([64, 184, 512]) + # (tensor_feat_curr_domain_curr_cls - feat_base_domain_curr_cls).shape: + # torch.Size([64, 184, 512]) # dist_same_class_base_domain_curr_domain.shape: # torch.Size([64, 184]) is the per element distance of # the cartesian product of feat_base_domain_curr_cls vs # tensor_feat_curr_domain_curr_cls - match_ind_base_domain_curr_domain = torch.argmin(dist_same_class_base_domain_curr_domain, dim=1) # the batch index of the neareast neighbors + match_ind_base_domain_curr_domain = torch.argmin( + dist_same_class_base_domain_curr_domain, dim=1 + ) + # the batch index of the neareast neighbors # len(match_ind_base_domain_curr_domain)=64 # theoretically match_ind_base_domain_curr_domain can # be a permutation of 0 to 183 though of size 64 @@ -225,19 +287,46 @@ def __call__(self, device, loader, phi, flag_match_min_dist): for idx in range(feat_base_domain_curr_cls.shape[0]): # counter_curr_cls_base_domain =0 at initialization - ### global_inds_base_domain_curr_cls pick out base + # ## global_inds_base_domain_curr_cls pick out base # domain class label y_c images - global_pos_base_domain_curr_cls = global_inds_base_domain_curr_cls[counter_curr_cls_base_domain].item() + global_pos_base_domain_curr_cls = ( + global_inds_base_domain_curr_cls[ + counter_curr_cls_base_domain + ].item() + ) if curr_domain_ind == base_domain_idx: - ind_match_global_curr_domain_curr_cls = global_pos_base_domain_curr_cls + ind_match_global_curr_domain_curr_cls = ( + global_pos_base_domain_curr_cls + ) else: if flag_match_min_dist: # if epoch > 0:match_min_dist=True - ind_match_global_curr_domain_curr_cls = global_inds_curr_domain_curr_cls[match_ind_base_domain_curr_domain[idx]].item() + ind_match_global_curr_domain_curr_cls = ( + global_inds_curr_domain_curr_cls[ + match_ind_base_domain_curr_domain[idx] + ].item() + ) else: # if epoch == 0 - ind_match_global_curr_domain_curr_cls = global_inds_curr_domain_curr_cls[counter_curr_cls_base_domain%size_curr_domain_curr_cls].item() - - self.dict_virtual_dset2each_domain[counter_ref_dset_size]['data'][curr_domain_ind] = self.dict_domain_data[curr_domain_ind]['data'][ind_match_global_curr_domain_curr_cls] - self.dict_virtual_dset2each_domain[counter_ref_dset_size]['label'][curr_domain_ind] = self.dict_domain_data[curr_domain_ind]['label'][ind_match_global_curr_domain_curr_cls] + ind_match_global_curr_domain_curr_cls = ( + global_inds_curr_domain_curr_cls[ + counter_curr_cls_base_domain + % size_curr_domain_curr_cls + ].item() + ) + + self.dict_virtual_dset2each_domain[counter_ref_dset_size][ + "data" + ][curr_domain_ind] = self.dict_domain_data[curr_domain_ind][ + "data" + ][ + ind_match_global_curr_domain_curr_cls + ] + self.dict_virtual_dset2each_domain[counter_ref_dset_size][ + "label" + ][curr_domain_ind] = self.dict_domain_data[curr_domain_ind][ + "label" + ][ + ind_match_global_curr_domain_curr_cls + ] # @FIXME: label initially were set to random continuous # value, which is a technique to check if # every data has been filled @@ -245,42 +334,67 @@ def __call__(self, device, loader, phi, flag_match_min_dist): counter_ref_dset_size += 1 if counter_ref_dset_size != self.virtual_ref_dset_size: - print("counter_ref_dset_size", counter_ref_dset_size) - print("self.virtual_ref_dset_size", self.virtual_ref_dset_size) - # warnings.warn("counter_ref_dset_size not equal to self.virtual_ref_dset_size") - raise RuntimeError("counter_ref_dset_size not equal to self.virtual_ref_dset_size") - + logger = Logger.get_logger() + logger.info(f"counter_ref_dset_size {counter_ref_dset_size}") + logger.info(f"self.virtual_ref_dset_size {self.virtual_ref_dset_size}") + logger.warning( + "counter_ref_dset_size not equal to self.virtual_ref_dset_size" + ) + raise RuntimeError( + "counter_ref_dset_size not equal to self.virtual_ref_dset_size" + ) for key in self.dict_virtual_dset2each_domain.keys(): - if self.dict_virtual_dset2each_domain[key]['label'].shape[0] != self.num_domains_tr: - raise RuntimeError("self.dict_virtual_dset2each_domain, \ + if ( + self.dict_virtual_dset2each_domain[key]["label"].shape[0] + != self.num_domains_tr + ): + raise RuntimeError( + "self.dict_virtual_dset2each_domain, \ one key correspond to value tensor not \ - equal to number of training domains") + equal to number of training domains" + ) # Sanity Check: Ensure paired points have the same class label wrong_case = 0 for key in self.dict_virtual_dset2each_domain.keys(): - for d_i in range(self.dict_virtual_dset2each_domain[key]['label'].shape[0]): - for d_j in range(self.dict_virtual_dset2each_domain[key]['label'].shape[0]): + for d_i in range(self.dict_virtual_dset2each_domain[key]["label"].shape[0]): + for d_j in range( + self.dict_virtual_dset2each_domain[key]["label"].shape[0] + ): if d_j > d_i: - if self.dict_virtual_dset2each_domain[key]['label'][d_i] != self.dict_virtual_dset2each_domain[key]['label'][d_j]: + if ( + self.dict_virtual_dset2each_domain[key]["label"][d_i] + != self.dict_virtual_dset2each_domain[key]["label"][d_j] + ): # raise RuntimeError("the reference domain has 'rows' with inconsistent class labels") wrong_case += 1 - print('Total Label MisMatch across pairs: ', wrong_case) + logger = Logger.get_logger() + logger.info(f"Total Label MisMatch across pairs: {wrong_case}") if wrong_case != 0: - raise RuntimeError("the reference domain \ - has 'rows' with inconsistent class labels") + raise RuntimeError( + "the reference domain has 'rows' with inconsistent class labels" + ) list_ref_domain_each_domain = [] list_ref_domain_each_domain_label = [] for ind_ref_domain_key in self.dict_virtual_dset2each_domain.keys(): - list_ref_domain_each_domain.append(self.dict_virtual_dset2each_domain[ind_ref_domain_key]['data']) - list_ref_domain_each_domain_label.append(self.dict_virtual_dset2each_domain[ind_ref_domain_key]['label']) + list_ref_domain_each_domain.append( + self.dict_virtual_dset2each_domain[ind_ref_domain_key]["data"] + ) + list_ref_domain_each_domain_label.append( + self.dict_virtual_dset2each_domain[ind_ref_domain_key]["label"] + ) tensor_ref_domain_each_domain_x = torch.stack(list_ref_domain_each_domain) - tensor_ref_domain_each_domain_label = torch.stack(list_ref_domain_each_domain_label) - - print(tensor_ref_domain_each_domain_x.shape, tensor_ref_domain_each_domain_label.shape) + tensor_ref_domain_each_domain_label = torch.stack( + list_ref_domain_each_domain_label + ) + + logger.info( + f"{tensor_ref_domain_each_domain_x.shape} " + f"{tensor_ref_domain_each_domain_label.shape}" + ) del self.dict_domain_data del self.dict_virtual_dset2each_domain diff --git a/domainlab/algos/compos/matchdg_utils.py b/domainlab/algos/trainers/compos/matchdg_utils.py similarity index 55% rename from domainlab/algos/compos/matchdg_utils.py rename to domainlab/algos/trainers/compos/matchdg_utils.py index 387393f21..62785e6a6 100644 --- a/domainlab/algos/compos/matchdg_utils.py +++ b/domainlab/algos/trainers/compos/matchdg_utils.py @@ -3,11 +3,14 @@ """ import torch +from domainlab.utils.logger import Logger -class MatchDictInit(): + +class MatchDictInit: """ base class for matching dictionary creator """ + def __init__(self, keys, vals, i_c, i_h, i_w): self.keys = keys self.vals = vals @@ -23,41 +26,55 @@ def __call__(self): for key in self.keys: dict_data[key] = {} num_rows = self.get_num_rows(key) - dict_data[key]['data'] = torch.rand((num_rows, self.i_c, self.i_w, self.i_h)) + dict_data[key]["data"] = torch.rand( + (num_rows, self.i_c, self.i_w, self.i_h) + ) # @FIXME: some labels won't be filled at all, when using training loader since the incomplete batch is dropped - dict_data[key]['label'] = torch.rand((num_rows, 1)) # scalar label - dict_data[key]['idx'] = torch.randint(low=0, high=1, size=(num_rows, 1)) + dict_data[key]["label"] = torch.rand((num_rows, 1)) # scalar label + dict_data[key]["idx"] = torch.randint(low=0, high=1, size=(num_rows, 1)) return dict_data -class MatchDictVirtualRefDset2EachDomain(MatchDictInit): +class MatchDictVirtualRefDset2EachDomain(MatchDictInit): """ dict[0:virtual_ref_dset_size] has tensor dimension: (num_domains_tr, i_c, i_h, i_w) """ + def __init__(self, virtual_ref_dset_size, num_domains_tr, i_c, i_h, i_w): """ virtual_ref_dset_size is a virtual dataset, len(virtual_ref_dset_size) = sum of all popular domains """ - super().__init__(keys=range(virtual_ref_dset_size), vals=num_domains_tr, - i_c=i_c, i_h=i_h, i_w=i_w) + super().__init__( + keys=range(virtual_ref_dset_size), + vals=num_domains_tr, + i_c=i_c, + i_h=i_h, + i_w=i_w, + ) def get_num_rows(self, key=None): """ key is 0:virtual_ref_dset_size """ - return self.vals # total_domains + return self.vals # total_domains class MatchDictNumDomain2SizeDomain(MatchDictInit): """ tensor dimension for the kth domain: [num_domains_tr, (size_domain_k, i_c, i_h, i_w)] """ + def __init__(self, num_domains_tr, list_tr_domain_size, i_c, i_h, i_w): - super().__init__(keys=range(num_domains_tr), vals=list_tr_domain_size, - i_c=i_c, i_h=i_h, i_w=i_w) + super().__init__( + keys=range(num_domains_tr), + vals=list_tr_domain_size, + i_c=i_c, + i_h=i_h, + i_w=i_w, + ) def get_num_rows(self, key): - return self.vals[key] # list_tr_domain_size[domain_index] + return self.vals[key] # list_tr_domain_size[domain_index] def dist_cosine_agg(x1, x2): @@ -67,10 +84,15 @@ def dist_cosine_agg(x1, x2): fun_cos = torch.nn.CosineSimilarity(dim=1, eps=1e-08) return 1.0 - fun_cos(x1, x2) + def fun_tensor_normalize(tensor_batch_x): eps = 1e-8 - batch_norm_x = tensor_batch_x.norm(dim=1) # Frobenius norm or Euclidean Norm long the embedding direction, len(norm) should be batch_size - batch_norm_x = batch_norm_x.view(batch_norm_x.shape[0], 1) # add dimension to tensor + batch_norm_x = tensor_batch_x.norm( + dim=1 + ) # Frobenius norm or Euclidean Norm long the embedding direction, len(norm) should be batch_size + batch_norm_x = batch_norm_x.view( + batch_norm_x.shape[0], 1 + ) # add dimension to tensor tensor_eps = eps * torch.ones_like(batch_norm_x) tensor_batch_x = tensor_batch_x / torch.max(batch_norm_x, tensor_eps) assert not torch.sum(torch.isnan(tensor_batch_x)) @@ -88,14 +110,43 @@ def dist_pairwise_cosine(x1, x2, tau=0.05): x1 = fun_tensor_normalize(x1) x2 = fun_tensor_normalize(x2) - x1_extended_dim = x1.unsqueeze(1) # Returns a new tensor with a dimension of size one inserted at the specified position. + x1_extended_dim = x1.unsqueeze( + 1 + ) # Returns a new tensor with a dimension of size one inserted at the specified position. # extend the order of by insering a new dimension so that cartesion product of pairwise distance can be calculated # since the batch size of x1 and x2 won't be the same, directly calculting elementwise product will cause an error # with order 3 multiply order 2 tensor, the feature dimension will be matched then the rest dimensions form cartesian product - cos_sim = torch.sum(x1_extended_dim*x2, dim=2) # elementwise product + cos_sim = torch.sum(x1_extended_dim * x2, dim=2) # elementwise product cos_sim = cos_sim / tau # make cosine similarity bigger than 1 assert not torch.sum(torch.isnan(cos_sim)) loss = torch.sum(torch.exp(cos_sim), dim=1) assert not torch.sum(torch.isnan(loss)) return loss + + +def get_base_domain_size4match_dg(task): + """ + Base domain is a dataset where each class + set come from one of the nominal domains + """ + # @FIXME: base domain should be calculated only on training domains + # instead of all the domains! + # domain_keys = task.get_list_domains() + domain_keys = task.list_domain_tr + base_domain_size = 0 + classes = task.list_str_y + for mclass in classes: + num = 0 + ref_domain = -1 + for _, domain_key in enumerate(domain_keys): + if task.dict_domain_class_count[domain_key][mclass] > num: + ref_domain = domain_key + num = task.dict_domain_class_count[domain_key][mclass] + logger = Logger.get_logger() + logger.info( + f"for class {mclass} bigest sample size is {num} " + f"ref domain is {ref_domain}" + ) + base_domain_size += num + return base_domain_size diff --git a/domainlab/algos/trainers/hyper_scheduler.py b/domainlab/algos/trainers/hyper_scheduler.py new file mode 100644 index 000000000..ee61504e1 --- /dev/null +++ b/domainlab/algos/trainers/hyper_scheduler.py @@ -0,0 +1,63 @@ +""" +update hyper-parameters during training +""" +import numpy as np + + +class HyperSchedulerWarmupLinear: + """ + HyperSchedulerWarmupLinear + """ + + def __init__(self, trainer, **kwargs): + """ + kwargs is a dictionary with key the hyper-parameter name and its value + """ + self.trainer = trainer + self.dict_par_setpoint = kwargs + self.total_steps = None + + def set_steps(self, total_steps): + """ + set number of total_steps to gradually change optimization parameter + """ + self.total_steps = total_steps + + def warmup(self, par_setpoint, epoch): + """warmup. + start from a small value of par to ramp up the steady state value using + # total_steps + :param epoch: + """ + ratio = ((epoch + 1) * 1.0) / self.total_steps + list_par = [par_setpoint, par_setpoint * ratio] + par = min(list_par) + return par + + def __call__(self, epoch): + dict_rst = {} + for key, val_setpoint in self.dict_par_setpoint.items(): + dict_rst[key] = self.warmup(val_setpoint, epoch) + return dict_rst + + +class HyperSchedulerWarmupExponential(HyperSchedulerWarmupLinear): + """ + HyperScheduler Exponential + """ + + def warmup(self, par_setpoint, epoch): + """ + start from a small value of par to ramp up the steady state value using + number of total_steps + :param epoch: + """ + percent_steps = ((epoch + 1) * 1.0) / self.total_steps + denominator = 1.0 + np.exp(-10 * percent_steps) + ratio = 2.0 / denominator - 1 + # percent_steps is 0, denom is 2, 2/denom is 1, ratio is 0 + # percent_steps is 1, denom is 1+exp(-10), 2/denom is 2/(1+exp(-10))=2, ratio is 1 + # exp(-10)=4.5e-5 is approximately 0 + # slowly increase the regularization weight from 0 to 1*alpha as epochs goes on + parval = float(ratio * par_setpoint) + return parval diff --git a/domainlab/algos/trainers/train_basic.py b/domainlab/algos/trainers/train_basic.py index cf24a2e0f..7e6d7cac7 100644 --- a/domainlab/algos/trainers/train_basic.py +++ b/domainlab/algos/trainers/train_basic.py @@ -1,18 +1,23 @@ """ basic trainer """ -from torch import optim +import math +from operator import add -from domainlab.algos.trainers.a_trainer import AbstractTrainer +import torch + +from domainlab import g_tensor_batch_agg +from domainlab.algos.trainers.a_trainer import AbstractTrainer, mk_opt + + +def list_divide(list_val, scalar): + return [ele / scalar for ele in list_val] class TrainerBasic(AbstractTrainer): """ basic trainer """ - def __init__(self, model, task, observer, device, aconf): - super().__init__(model, task, observer, device, aconf) - self.optimizer = optim.Adam(self.model.parameters(), lr=aconf.lr) def before_tr(self): """ @@ -20,18 +25,84 @@ def before_tr(self): """ self.model.evaluate(self.loader_te, self.device) - def tr_epoch(self, epoch): + def before_epoch(self): + """ + set model to train mode + initialize some member variables + """ self.model.train() + self.counter_batch = 0.0 self.epo_loss_tr = 0 - for ind_batch, (tensor_x, vec_y, vec_d, *others) in enumerate(self.loader_tr): - tensor_x, vec_y, vec_d = \ - tensor_x.to(self.device), vec_y.to(self.device), vec_d.to(self.device) - self.optimizer.zero_grad() - loss = self.model.cal_loss(tensor_x, vec_y, vec_d, others) - loss = loss.sum() - loss.backward() - self.optimizer.step() - self.epo_loss_tr += loss.detach().item() - self.after_batch(epoch, ind_batch) + self.epo_reg_loss_tr = [0.0 for _ in range(10)] + self.epo_task_loss_tr = 0 + + def tr_epoch(self, epoch): + self.before_epoch() + for ind_batch, (tensor_x, tensor_y, tensor_d, *others) in enumerate( + self.loader_tr + ): + self.tr_batch(tensor_x, tensor_y, tensor_d, others, ind_batch, epoch) + return self.after_epoch(epoch) + + def after_epoch(self, epoch): + """ + observer collect information + """ + self.epo_loss_tr /= self.counter_batch + self.epo_task_loss_tr /= self.counter_batch + self.epo_reg_loss_tr = list_divide(self.epo_reg_loss_tr, self.counter_batch) + assert self.epo_loss_tr is not None + assert not math.isnan(self.epo_loss_tr) flag_stop = self.observer.update(epoch) # notify observer + assert flag_stop is not None return flag_stop + + def log_loss(self, list_b_reg_loss, loss_task, loss): + """ + just for logging the self.epo_reg_loss_tr + """ + self.epo_task_loss_tr += loss_task.sum().detach().item() + # + list_b_reg_loss_sumed = [ele.sum().detach().item() for ele in list_b_reg_loss] + self.epo_reg_loss_tr = list( + map(add, self.epo_reg_loss_tr, list_b_reg_loss_sumed) + ) + self.epo_loss_tr += loss.detach().item() + + def tr_batch(self, tensor_x, tensor_y, tensor_d, others, ind_batch, epoch): + """ + optimize neural network one step upon a mini-batch of data + """ + self.before_batch(epoch, ind_batch) + tensor_x, tensor_y, tensor_d = ( + tensor_x.to(self.device), + tensor_y.to(self.device), + tensor_d.to(self.device), + ) + self.optimizer.zero_grad() + loss = self.cal_loss(tensor_x, tensor_y, tensor_d, others) + loss.backward() + self.optimizer.step() + self.after_batch(epoch, ind_batch) + self.counter_batch += 1 + + def cal_loss(self, tensor_x, tensor_y, tensor_d, others): + """ + so that user api can use trainer.cal_loss to train + """ + loss_task = self.model.cal_task_loss(tensor_x, tensor_y) + + list_reg_tr_batch, list_mu_tr = self.cal_reg_loss( + tensor_x, tensor_y, tensor_d, others + ) + tensor_batch_reg_loss_penalized = self.model.list_inner_product( + list_reg_tr_batch, list_mu_tr + ) + assert len(tensor_batch_reg_loss_penalized.shape) == 1 + loss_erm_agg = g_tensor_batch_agg(loss_task) + loss_reg_penalized_agg = g_tensor_batch_agg(tensor_batch_reg_loss_penalized) + loss_penalized = ( + self.model.multiplier4task_loss * loss_erm_agg + loss_reg_penalized_agg + ) + self.log_loss(list_reg_tr_batch, loss_task, loss_penalized) + return loss_penalized diff --git a/domainlab/algos/trainers/train_dial.py b/domainlab/algos/trainers/train_dial.py index a7307d5da..75a5e34f0 100644 --- a/domainlab/algos/trainers/train_dial.py +++ b/domainlab/algos/trainers/train_dial.py @@ -11,20 +11,22 @@ class TrainerDIAL(TrainerBasic): """ Trainer Domain Invariant Adversarial Learning """ + def gen_adversarial(self, device, img_natural, vec_y): """ use naive trimming to find optimize img in the direction of adversarial gradient, this is not necessarily constraint optimal due to nonlinearity, as the constraint epsilon is only considered ad-hoc """ - # @FIXME: is there better way to initialize adversarial image? # ensure adversarial image not in computational graph steps_perturb = self.aconf.dial_steps_perturb scale = self.aconf.dial_noise_scale step_size = self.aconf.dial_lr epsilon = self.aconf.dial_epsilon img_adv_ini = img_natural.detach() - img_adv_ini = img_adv_ini + scale * torch.randn(img_natural.shape).to(device).detach() + img_adv_ini = ( + img_adv_ini + scale * torch.randn(img_natural.shape).to(device).detach() + ) img_adv = img_adv_ini for _ in range(steps_perturb): img_adv.requires_grad_() @@ -32,32 +34,19 @@ def gen_adversarial(self, device, img_natural, vec_y): grad = torch.autograd.grad(loss_gen_adv, [img_adv])[0] # instead of gradient descent, we gradient ascent here img_adv = img_adv_ini.detach() + step_size * torch.sign(grad.detach()) - img_adv = torch.min(torch.max(img_adv, img_natural - epsilon), img_natural + epsilon) + img_adv = torch.min( + torch.max(img_adv, img_natural - epsilon), img_natural + epsilon + ) img_adv = torch.clamp(img_adv, 0.0, 1.0) return img_adv - def tr_batch(self, epoch, ind_batch): + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): """ - anneal parameter for each batch + Let trainer behave like a model, so that other trainer could use it """ - self.model.hyper_update(epoch*self.num_batches + ind_batch, self.hyper_scheduler) - return super().tr_epoch(epoch) - - def tr_epoch(self, epoch): - self.model.train() - self.epo_loss_tr = 0 - for ind_batch, (tensor_x, vec_y, vec_d, *_) in enumerate(self.loader_tr): - tensor_x, vec_y, vec_d = \ - tensor_x.to(self.device), vec_y.to(self.device), vec_d.to(self.device) - self.optimizer.zero_grad() - loss = self.model.cal_loss(tensor_x, vec_y, vec_d) # @FIXME - tensor_x_adv = self.gen_adversarial(self.device, tensor_x, vec_y) - tensor_x_batch_adv_no_grad = Variable(tensor_x_adv, requires_grad=False) - loss_dial = self.model.cal_loss(tensor_x_batch_adv_no_grad, vec_y, vec_d) # @FIXME - loss = loss.sum() + self.aconf.gamma_reg * loss_dial.sum() - loss.backward() - self.optimizer.step() - self.epo_loss_tr += loss.detach().item() - self.after_batch(epoch, ind_batch) - flag_stop = self.observer.update(epoch) # notify observer - return flag_stop + _ = tensor_d + _ = others + tensor_x_adv = self.gen_adversarial(self.device, tensor_x, tensor_y) + tensor_x_batch_adv_no_grad = Variable(tensor_x_adv, requires_grad=False) + loss_dial = self.model.cal_task_loss(tensor_x_batch_adv_no_grad, tensor_y) + return [loss_dial], [self.aconf.gamma_reg] diff --git a/domainlab/algos/trainers/train_fishr.py b/domainlab/algos/trainers/train_fishr.py new file mode 100644 index 000000000..1a11e3780 --- /dev/null +++ b/domainlab/algos/trainers/train_fishr.py @@ -0,0 +1,171 @@ +""" +use random start to generate adversarial images +""" + +from collections import OrderedDict +import torch +from torch import nn + +try: + from backpack import backpack, extend + from backpack.extensions import Variance +except: + backpack = None + +from domainlab.algos.trainers.train_basic import TrainerBasic + + +class TrainerFishr(TrainerBasic): + """ + The goal is to minimize the variance of the domain-level variance of the gradients. + This aligns the domain-level loss landscapes locally around the final weights, reducing + inconsistencies across domains. + + For more details, see: Alexandre Ramé, Corentin Dancette, and Matthieu Cord. + "Fishr: Invariant gradient variances for out-of-distribution generalization." + International Conference on Machine Learning. PMLR, 2022. + """ + def tr_epoch(self, epoch): + list_loaders = list(self.dict_loader_tr.values()) + loaders_zip = zip(*list_loaders) + self.model.train() + self.model.convert4backpack() + self.epo_loss_tr = 0 + + for ind_batch, tuple_data_domains_batch in enumerate(loaders_zip): + self.optimizer.zero_grad() + list_dict_var_grads, list_loss_erm = self.var_grads_and_loss(tuple_data_domains_batch) + dict_layerwise_var_var_grads = self.variance_between_dict(list_dict_var_grads) + dict_layerwise_var_var_grads_sum = \ + {key: val.sum() for key, val in dict_layerwise_var_var_grads.items()} + loss_fishr = sum(dict_layerwise_var_var_grads_sum.values()) + loss = sum(list_loss_erm) + self.aconf.gamma_reg * loss_fishr + loss.backward() + self.optimizer.step() + self.epo_loss_tr += loss.detach().item() + self.after_batch(epoch, ind_batch) + + flag_stop = self.observer.update(epoch) # notify observer + return flag_stop + + def var_grads_and_loss(self, tuple_data_domains_batch): + """ + Calculate the domain-level variance of the gradients and the layer-wise erm loss. + Input: a tupel containing lists with the data per domain + Return: two lists. The first one contains dictionaries with the gradient variances. The keys + are the layers and the values are tensors. The gradient variances are stored in the tensors. + The second list contains the losses. Each list entry represents the summed up erm loss of a + single layer. + """ + + list_dict_var_grads = [] + list_loss_erm = [] + for list_x_y_d_single_domain in tuple_data_domains_batch: # traverse each domain + # first dimension of tensor_x is batchsize + tensor_x, vec_y, vec_d, *_ = tuple(list_x_y_d_single_domain) + tensor_x, vec_y, vec_d = \ + tensor_x.to(self.device), vec_y.to(self.device), vec_d.to(self.device) + dict_var_grads_single_domain = self.cal_dict_variance_grads(tensor_x, vec_y) + list_dict_var_grads.append(dict_var_grads_single_domain) + loss_erm, *_ = self.model.cal_loss(tensor_x, vec_y, vec_d) + list_loss_erm.append(loss_erm.sum()) # FIXME: let sum() to be configurable + # now len(list_dict_var_grads) = (# domains) + return list_dict_var_grads, list_loss_erm + + + def variance_between_dict(self, list_dict_var_paragrad): + """ + Computes the variance of the domain-level gradient variances, layer-wise. + Let $v=1/n\\sum_i^n v_i represent the mean across n domains, with + $$v_i = var(\\nabla_{\\theta}\\ell(x^{(d_i)}, y^{(d_i)}))$$, where $$d_i$$ means data + coming from domain i. We are interested in $1/n\\sum_(v_i-v)^2=1/n \\sum_i v_i^2 - v^2$. + + Input: list of dictionaries, each dictionary has the structure + {"layer1": tensor[64, 3, 11, 11], + "layer2": tensor[8, 3, 5, 5]}..... + The scalar values in the dictionary are the variances of the gradient of the loss + w.r.t. the scalar component of the weight tensor for the layer in question, where + the variance is computed w.r.t. the minibatch of a particular domain. + + Return: dictionary, containing the layers as keys and tensors as values. The variances are + stored in the tensors as scalars. + """ + + dict_d1 = list_dict_var_paragrad[0] + # first we determine \\bar(v^2) + list_dict_var_paragrad_squared = [{key:torch.pow(dict_ele[key], 2) for key in dict_d1} + for dict_ele in list_dict_var_paragrad] + dict_mean_square_var_paragrad = self.cal_mean_across_dict(list_dict_var_paragrad_squared) + + # now we determine $\\bar(v)^2$ + dict_mean_var_paragrad = \ + {key: torch.mean(torch.stack([ele[key] for ele in list_dict_var_paragrad]), dim=0) + for key in dict_d1.keys()} + dict_square_mean_var_paragrad = self.cal_power_single_dict(dict_mean_var_paragrad) + + # now we do \bar(v^2)- (\bar(v))² + dict_layerwise_var_var_grads = \ + {key:dict_mean_square_var_paragrad[key]-dict_square_mean_var_paragrad[key] + for key in dict_square_mean_var_paragrad.keys()} + return dict_layerwise_var_var_grads + + def cal_power_single_dict(self, mdict): + """ + Calculates the element-wise power of the values in a dictionary, when the values ar tensors. + Input: dictionary, where the values are tensors. + Return: dictionary, where the values are tensors. The scalar values of the tensors are the + element-wise power of the scalars in the input dictionary. + """ + + dict_rst = {key:torch.pow(mdict[key], 2) for key in mdict} + return dict_rst + + def cal_mean_across_dict(self, list_dict): + """ + Calculates the mean across several dictionaries. + Input: list of dictionaries, where the values of each dictionary are tensors. + Return: dictionary, where the values are tensors. The scalar values of the tensors contain + the mean across the first dimension of the dictionaries from the list of inputs. + """ + + dict_d1 = list_dict[0] + dict_mean_var_paragrad = \ + {key: torch.mean(torch.stack([ele[key] for ele in list_dict]), dim=0) + for key in dict_d1.keys()} + return dict_mean_var_paragrad + + def cal_dict_variance_grads(self, tensor_x, vec_y): + """ + Calculates the domain-level variances of the gradients w.r.t. the scalar component of the + weight tensor for the layer in question, i.e. + $$v_i = var(\\nabla_{\\theta}\\ell(x^{(d_i)}, y^{(d_i)}))$$, where $$d_i$$ means data + coming from domain i. The computation is done using the package backpack. + + Input: tensor_x, a tensor, where the first dimension is the batch size and vec_y, which + is a vector representing the output labels. + + Return: dictionary, where the key is the name for the layer of a neural network and the + value is the diagonal variance of each scalar component of the gradient of the loss w.r.t. + the parameter. + + Return Example: + {"layer1": Tensor[batchsize=32, 64, 3, 11, 11 ]} as a convolution kernel + """ + + loss = self.model.cal_task_loss(tensor_x.clone(), vec_y) + loss = loss.sum() + + with backpack(Variance()): + loss.backward( + inputs=list(self.model.parameters()), retain_graph=True, create_graph=True + ) + + for name, param in self.model.named_parameters(): + print(name) + print(".grad.shape: ", param.variance.shape) + + dict_variance = OrderedDict( + [(name, weights.variance.clone()) + for name, weights in self.model.named_parameters() + ]) + return dict_variance diff --git a/domainlab/algos/trainers/train_hyper_scheduler.py b/domainlab/algos/trainers/train_hyper_scheduler.py new file mode 100644 index 000000000..2e60bf5e8 --- /dev/null +++ b/domainlab/algos/trainers/train_hyper_scheduler.py @@ -0,0 +1,64 @@ +""" +update hyper-parameters during training +""" +from domainlab.algos.trainers.hyper_scheduler import HyperSchedulerWarmupLinear +from domainlab.algos.trainers.train_basic import TrainerBasic +from domainlab.utils.logger import Logger + + +class TrainerHyperScheduler(TrainerBasic): + """ + TrainerHyperScheduler + """ + + def set_scheduler( + self, scheduler, total_steps, flag_update_epoch=False, flag_update_batch=False + ): + """ + set the warmup strategy from objective scheduler + set wheter the hyper-parameter scheduling happens per epoch or per batch + + Args: + scheduler: The class name of the scheduler, the object corresponding to + this class name will be created inside model + total_steps: number of steps to change the hyper-parameters + flag_update_epoch: if hyper-parameters should be changed per epoch + flag_update_batch: if hyper-parameters should be changed per batch + """ + self.hyper_scheduler = self.model.hyper_init(scheduler) + # let model register its hyper-parameters to the scheduler + self.flag_update_hyper_per_epoch = flag_update_epoch + self.flag_update_hyper_per_batch = flag_update_batch + self.hyper_scheduler.set_steps(total_steps=total_steps) + + def before_batch(self, epoch, ind_batch): + """ + if hyper-parameters should be updated per batch, then step + should be set to epoch*self.num_batches + ind_batch + """ + if self.flag_update_hyper_per_batch: + self.model.hyper_update( + epoch * self.num_batches + ind_batch, self.hyper_scheduler + ) + return super().before_batch(epoch, ind_batch) + + def before_tr(self): + if self.hyper_scheduler is None: + logger = Logger.get_logger() + logger.warning( + "hyper-parameter scheduler not set," + "going to use default Warmpup and epoch update" + ) + self.set_scheduler( + HyperSchedulerWarmupLinear, + total_steps=self.aconf.warmup, + flag_update_epoch=True, + ) + + def tr_epoch(self, epoch): + """ + update hyper-parameters only per epoch + """ + if self.flag_update_hyper_per_epoch: + self.model.hyper_update(epoch, self.hyper_scheduler) + return super().tr_epoch(epoch) diff --git a/domainlab/algos/trainers/train_matchdg.py b/domainlab/algos/trainers/train_matchdg.py index 13925761b..6a3edd996 100644 --- a/domainlab/algos/trainers/train_matchdg.py +++ b/domainlab/algos/trainers/train_matchdg.py @@ -1,40 +1,371 @@ -from domainlab.algos.compos.matchdg_ctr_erm import MatchCtrErm +""" +trainer matchdg +""" +import torch + +from domainlab import g_inst_component_loss_agg, g_list_loss_agg from domainlab.algos.trainers.a_trainer import AbstractTrainer +from domainlab.algos.trainers.compos.matchdg_match import MatchPair +from domainlab.algos.trainers.compos.matchdg_utils import ( + dist_cosine_agg, + dist_pairwise_cosine, + get_base_domain_size4match_dg, +) +from domainlab.tasks.utils_task_dset import DsetIndDecorator4XYD +from domainlab.utils.logger import Logger class TrainerMatchDG(AbstractTrainer): - def __init__(self, exp, task, ctr_model, model, observer, args, device): - super().__init__(model, task, observer, device, args) - self.exp = exp - self.epo_loss_tr = None - self.ctr_model = ctr_model - self.args = self.aconf + """ + Contrastive Learning + """ - def before_tr(self): + def dset_decoration_args_algo(self, args, ddset): + ddset = DsetIndDecorator4XYD(ddset) + return ddset + + def init_business( + self, model, task, observer, device, aconf, flag_accept=True, flag_erm=False + ): """ - configure trainer accoding to properties of task as well according to algorithm configs + initialize member objects """ - # @FIXME: aconf and args should be separated - # phase 1: contrastive learning - ctr = MatchCtrErm(exp=self.exp, - task=self.task, - phi=self.ctr_model, - args=self.args, - device=self.device, - flag_erm=False) - ctr.train() - print("Phase 1 finished: ", ctr.ctr_mpath) - # phase 2: ERM, initialize object - self.erm = MatchCtrErm(phi=self.model, - exp=self.exp, - task=self.task, - args=self.args, - device=self.device, - flag_erm=True) + super().init_business(model, task, observer, device, aconf, flag_accept) + # use the same batch size for match tensor + # so that order is kept! + self.base_domain_size = get_base_domain_size4match_dg(self.task) + self.epo_loss_tr = 0 + self.flag_erm = flag_erm + self.lambda_ctr = self.aconf.gamma_reg + self.mk_match_tensor(epoch=0) + self.flag_match_tensor_sweep_over = False + self.tuple_tensor_ref_domain2each_y = None + self.tuple_tensor_refdomain2each = None def tr_epoch(self, epoch): + """ + # data in one batch comes from two sources: one part from loader, + # the other part from match tensor + """ self.model.train() - self.erm.tr_epoch(epoch) - self.epo_loss_tr = self.erm.epo_loss_tr + self.epo_loss_tr = 0 + logger = Logger.get_logger() + # update match tensor + if (epoch + 1) % self.aconf.epos_per_match_update == 0: + self.mk_match_tensor(epoch) + + inds_shuffle = torch.randperm(self.tensor_ref_domain2each_domain_x.size(0)) + # NOTE: match tensor size: N(ref domain size) * #(train domains) * (image size: c*h*w) + # self.tensor_ref_domain2each_domain_x[inds_shuffle] + # shuffles the match tensor at the first dimension + self.tuple_tensor_refdomain2each = torch.split( + self.tensor_ref_domain2each_domain_x[inds_shuffle], self.aconf.bs, dim=0 + ) + # Splits the tensor into chunks. + # Each chunk is a view of the original tensor of batch size self.aconf.bs + # return is a tuple of the splited chunks + self.tuple_tensor_ref_domain2each_y = torch.split( + self.tensor_ref_domain2each_domain_y[inds_shuffle], self.aconf.bs, dim=0 + ) + logger.info( + f"number of batches in match tensor: {len(self.tuple_tensor_refdomain2each)}" + ) + logger.info( + f"single batch match tensor size: {self.tuple_tensor_refdomain2each[0].shape}" + ) + + for batch_idx, (x_e, y_e, d_e, *others) in enumerate(self.loader_tr): + # random loader with same batch size as the match tensor loader + # the 4th output of self.loader is not used at all, + # is only used for creating the match tensor + self.tr_batch(epoch, batch_idx, x_e, y_e, d_e, others) + if self.flag_match_tensor_sweep_over is True: + logger.info( + "ref/base domain vs each domain match \ + traversed one sweep, starting new epoch" + ) + self.flag_match_tensor_sweep_over = False + break + + if epoch < self.aconf.epochs_ctr: + logger.info("\n\nPhase ctr-only continue\n\n") + self.observer.reset() + return False + + logger.info("\n\nPhase erm+ctr \n\n") + self.flag_erm = True flag_stop = self.observer.update(epoch) # notify observer return flag_stop + + def tr_batch(self, epoch, batch_idx, x_e, y_e, d_e, others=None): + """ + update network for each batch + """ + self.optimizer.zero_grad() + x_e = x_e.to(self.device) # 64 * 1 * 224 * 224 + # y_e_scalar = torch.argmax(y_e, dim=1).to(self.device) + y_e = y_e.to(self.device) + # d_e = torch.argmax(d_e, dim=1).numpy() + d_e = d_e.to(self.device) + # for each batch, the list loss is re-initialized + + # CTR (contrastive) loss for CTR/ERM phase are different + list_batch_loss_ctr = [] + # for a single batch, loss need to be + # aggregated across different combinations of domains. + # Defining a leaf node can cause problem by loss_ctr += xxx, + # a list with python built-in "sum" can aggregate + # these losses within one batch + + if self.flag_erm: + # decoratee can be both trainer or model + list_loss_reg_rand, list_mu_reg = self.decoratee.cal_reg_loss( + x_e, y_e, d_e, others + ) + loss_reg = self.model.list_inner_product(list_loss_reg_rand, list_mu_reg) + loss_task_rand = self.model.cal_task_loss(x_e, y_e) + # loss_erm_rnd_loader, *_ = self.model.cal_loss(x_e, y_e, d_e, others) + loss_erm_rnd_loader = ( + loss_reg + loss_task_rand * self.model.multiplier4task_loss + ) + + num_batches_match_tensor = len(self.tuple_tensor_refdomain2each) + + if batch_idx >= num_batches_match_tensor: + self.flag_match_tensor_sweep_over = True + return + + curr_batch_size = self.tuple_tensor_refdomain2each[batch_idx].shape[0] + + batch_tensor_ref_domain2each = self.tuple_tensor_refdomain2each[batch_idx].to( + self.device + ) + # make order 5 tensor: (ref_domain, domain, channel, img_h, img_w) + # with first dimension as batch size + + # clamp the first two dimensions so the model network could map image to feature + batch_tensor_ref_domain2each = match_tensor_reshape( + batch_tensor_ref_domain2each + ) + # now batch_tensor_ref_domain2each first dim will not be batch_size! + # batch_tensor_ref_domain2each.shape torch.Size([40, channel, 224, 224]) + + batch_feat_ref_domain2each = self.model.extract_semantic_feat( + batch_tensor_ref_domain2each + ) + # batch_feat_ref_domain2each.shape torch.Size[40, 512] + # torch.sum(torch.isnan(batch_tensor_ref_domain2each)) + # assert not torch.sum(torch.isnan(batch_feat_ref_domain2each)) + flag_isnan = torch.any(torch.isnan(batch_feat_ref_domain2each)) + if flag_isnan: + logger = Logger.get_logger() + logger.info(batch_tensor_ref_domain2each) + raise RuntimeError( + "batch_feat_ref_domain2each NAN! is learning rate too big or" + "hyper-parameter tau not set appropriately?" + ) + + # for contrastive training phase, + # the last layer of the model is replaced with identity + + batch_ref_domain2each_y = self.tuple_tensor_ref_domain2each_y[batch_idx].to( + self.device + ) + batch_ref_domain2each_y = batch_ref_domain2each_y.view( + batch_ref_domain2each_y.shape[0] * batch_ref_domain2each_y.shape[1] + ) + + if self.flag_erm: + # @FIXME: check if batch_ref_domain2each_y is + # continuous number which means it is at its initial value, + # not yet filled + loss_erm_match_tensor, *_ = self.model.cal_task_loss( + batch_tensor_ref_domain2each, batch_ref_domain2each_y.long() + ) + + # Creating tensor of shape (domain size, total domains, feat size ) + # The match tensor's first two dimension + # [(Ref domain size) * (# train domains)] + # has been clamped together to get features extracted + # through self.model + + # it has to be reshaped into the match tensor shape, the same + # for the extracted feature here, it has to reshaped into + # the shape of the match tensor + # to make sure that the reshape only happens at the + # first two dimension, the feature dim has to be kept intact + dim_feat = batch_feat_ref_domain2each.shape[1] + num_domain_tr = len(self.task.list_domain_tr) + batch_feat_ref_domain2each = batch_feat_ref_domain2each.view( + curr_batch_size, num_domain_tr, dim_feat + ) + + batch_ref_domain2each_y = batch_ref_domain2each_y.view( + curr_batch_size, num_domain_tr + ) + + # The match tensor's first two dimension + # [(Ref domain size) * (# train domains)] has been clamped + # together to get features extracted through self.model + batch_tensor_ref_domain2each = batch_tensor_ref_domain2each.view( + curr_batch_size, + num_domain_tr, + batch_tensor_ref_domain2each.shape[1], # channel + batch_tensor_ref_domain2each.shape[2], # img_h + batch_tensor_ref_domain2each.shape[3], + ) # img_w + + # Contrastive Loss: class \times domain \times domain + counter_same_cls_diff_domain = 1 + logger = Logger.get_logger() + for y_c in range(self.task.dim_y): + subset_same_cls = batch_ref_domain2each_y[:, 0] == y_c + subset_diff_cls = batch_ref_domain2each_y[:, 0] != y_c + feat_same_cls = batch_feat_ref_domain2each[subset_same_cls] + feat_diff_cls = batch_feat_ref_domain2each[subset_diff_cls] + logger.debug( + f"class {y_c} with same class and different class: " + + f"{feat_same_cls.shape[0]} {feat_diff_cls.shape[0]}" + ) + + if feat_same_cls.shape[0] == 0 or feat_diff_cls.shape[0] == 0: + logger.debug( + f"no instances of label {y_c}" f"in the current batch, continue" + ) + continue + + if torch.sum(torch.isnan(feat_diff_cls)): + raise RuntimeError("feat_diff_cls has nan entrie(s)") + + feat_diff_cls = feat_diff_cls.view( + feat_diff_cls.shape[0] * feat_diff_cls.shape[1], feat_diff_cls.shape[2] + ) + + for d_i in range(feat_same_cls.shape[1]): + dist_diff_cls_same_domain = dist_pairwise_cosine( + feat_same_cls[:, d_i, :], feat_diff_cls[:, :] + ) + + if torch.sum(torch.isnan(dist_diff_cls_same_domain)): + raise RuntimeError("dist_diff_cls_same_domain NAN") + + # iterate other domains + for d_j in range(feat_same_cls.shape[1]): + if d_i >= d_j: + continue + dist_same_cls_diff_domain = dist_cosine_agg( + feat_same_cls[:, d_i, :], feat_same_cls[:, d_j, :] + ) + + if torch.sum(torch.isnan(dist_same_cls_diff_domain)): + raise RuntimeError("dist_same_cls_diff_domain NAN") + + # CTR (contrastive) loss is exclusive for + # CTR phase and ERM phase + + if self.flag_erm: + list_batch_loss_ctr.append(torch.sum(dist_same_cls_diff_domain)) + else: + i_dist_same_cls_diff_domain = 1.0 - dist_same_cls_diff_domain + i_dist_same_cls_diff_domain = ( + i_dist_same_cls_diff_domain / self.aconf.tau + ) + partition = torch.log( + torch.exp(i_dist_same_cls_diff_domain) + + dist_diff_cls_same_domain + ) + list_batch_loss_ctr.append( + -1 * torch.sum(i_dist_same_cls_diff_domain - partition) + ) + + counter_same_cls_diff_domain += dist_same_cls_diff_domain.shape[0] + + loss_ctr = g_list_loss_agg(list_batch_loss_ctr) / counter_same_cls_diff_domain + + if self.flag_erm: + epos = self.aconf.epos + else: + epos = self.aconf.epochs_ctr + percentage_finished_epochs = (epoch + 1) / (epos + 1) + # loss aggregation is over different domain + # combinations of the same batch + # https://discuss.pytorch.org/t/leaf-variable-was-used-in-an-inplace-operation/308 + # Loosely, tensors you create directly are leaf variables. + # Tensors that are the result of a differentiable operation are + # not leaf variables + + if self.flag_erm: + # extra loss of ERM phase: the ERM loss + # (the CTR loss for the ctr phase and erm phase are different) + # erm loss comes from two different data loaders, + # one is rnd (random) data loader + # the other one is the data loader from the match tensor + loss_e = ( + torch.tensor(0.0, requires_grad=True) + + g_inst_component_loss_agg(loss_erm_rnd_loader) + + g_inst_component_loss_agg(loss_erm_match_tensor) + * self.model.multiplier4task_loss + + self.lambda_ctr * percentage_finished_epochs * loss_ctr + ) + else: + loss_e = ( + torch.tensor(0.0, requires_grad=True) + + self.lambda_ctr * percentage_finished_epochs * loss_ctr + ) + # @FIXME: without torch.tensor(0.0), after a few epochs, + # error "'float' object has no attribute 'backward'" + + loss_e.backward(retain_graph=False) + self.optimizer.step() + self.epo_loss_tr += loss_e.detach().item() + + torch.cuda.empty_cache() + + def mk_match_tensor(self, epoch): + """ + initialize or update match tensor + """ + obj_match = MatchPair( + self.task.dim_y, + self.task.isize.i_c, + self.task.isize.i_h, + self.task.isize.i_w, + self.aconf.bs, + virtual_ref_dset_size=self.base_domain_size, + num_domains_tr=len(self.task.list_domain_tr), + list_tr_domain_size=self.list_tr_domain_size, + ) + + # @FIXME: what is the usefulness of (epoch > 0) as argument + ( + self.tensor_ref_domain2each_domain_x, + self.tensor_ref_domain2each_domain_y, + ) = obj_match( + self.device, + self.task.loader_tr, + self.model.extract_semantic_feat, + (epoch > 0), + ) + + def before_tr(self): + """ + override abstract method + """ + logger = Logger.get_logger() + logger.info("\n\nPhase 1 start: contractive alignment without task loss: \n\n") + # phase 1: contrastive learning + # different than phase 2, ctr_model has no classification loss + + +def match_tensor_reshape(batch_tensor_ref_domain2each): + """ + # original dimension is (ref_domain, domain, (channel, img_h, img_w)) + # use a function so it is easier to accomodate other data mode (not image) + """ + batch_tensor_refdomain_other_domain_chw = batch_tensor_ref_domain2each.view( + batch_tensor_ref_domain2each.shape[0] * batch_tensor_ref_domain2each.shape[1], + batch_tensor_ref_domain2each.shape[2], # channel + batch_tensor_ref_domain2each.shape[3], # img_h + batch_tensor_ref_domain2each.shape[4], + ) # img_w + return batch_tensor_refdomain_other_domain_chw diff --git a/domainlab/algos/trainers/train_mldg.py b/domainlab/algos/trainers/train_mldg.py new file mode 100644 index 000000000..90318286c --- /dev/null +++ b/domainlab/algos/trainers/train_mldg.py @@ -0,0 +1,120 @@ +""" +Meta Learning Domain Generalization +""" +import copy +import random + +from torch.utils.data.dataset import ConcatDataset + +from domainlab.algos.trainers.a_trainer import AbstractTrainer +from domainlab.algos.trainers.train_basic import TrainerBasic +from domainlab.tasks.utils_task import mk_loader +from domainlab.tasks.utils_task_dset import DsetZip + + +class TrainerMLDG(AbstractTrainer): + """ + basic trainer + """ + + def before_tr(self): + """ + check the performance of randomly initialized weight + """ + self.model.evaluate(self.loader_te, self.device) + self.inner_trainer = TrainerBasic() + self.inner_trainer.extend(self._decoratee) + inner_model = copy.deepcopy(self.model) + self.inner_trainer.init_business( + inner_model, + copy.deepcopy(self.task), + self.observer, + self.device, + self.aconf, + flag_accept=False, + ) + self.prepare_ziped_loader() + + def prepare_ziped_loader(self): + """ + create virtual source and target domain + """ + list_dsets = list(self.task.dict_dset_tr.values()) + num_domains = len(list_dsets) + ind_target_domain = random.randrange(num_domains) + tuple_dsets_source = tuple( + list_dsets[ind] for ind in range(num_domains) if ind != ind_target_domain + ) + ddset_source = ConcatDataset(tuple_dsets_source) + ddset_target = list_dsets[ind_target_domain] + ddset_mix = DsetZip(ddset_source, ddset_target) + self.loader_tr_source_target = mk_loader(ddset_mix, self.aconf.bs) + + def tr_epoch(self, epoch): + self.model.train() + self.epo_loss_tr = 0 + self.prepare_ziped_loader() + # s means source, t means target + for ind_batch, ( + tensor_x_s, + vec_y_s, + vec_d_s, + others_s, + tensor_x_t, + vec_y_t, + vec_d_t, + *_, + ) in enumerate(self.loader_tr_source_target): + tensor_x_s, vec_y_s, vec_d_s = ( + tensor_x_s.to(self.device), + vec_y_s.to(self.device), + vec_d_s.to(self.device), + ) + + tensor_x_t, vec_y_t, vec_d_t = ( + tensor_x_t.to(self.device), + vec_y_t.to(self.device), + vec_d_t.to(self.device), + ) + + self.optimizer.zero_grad() + + self.inner_trainer.model.load_state_dict(self.model.state_dict()) + # update inner_model + self.inner_trainer.before_epoch() # set model to train mode + self.inner_trainer.reset() # force optimizer to re-initialize + self.inner_trainer.tr_batch( + tensor_x_s, vec_y_s, vec_d_s, others_s, ind_batch, epoch + ) + # inner_model has now accumulated gradients Gi + # with parameters theta_i - lr * G_i where i index batch + + loss_look_forward = self.inner_trainer.model.cal_task_loss( + tensor_x_t, vec_y_t + ) + loss_source_task = self.model.cal_task_loss(tensor_x_s, vec_y_s) + list_source_reg_tr, list_source_mu_tr = self.cal_reg_loss( + tensor_x_s, vec_y_s, vec_d_s, others_s + ) + # call cal_reg_loss from decoratee + # super()._cal_reg_loss returns [],[], + # since mldg's reg loss is on target domain, + # no other trainer except hyperscheduler could decorate it unless we use state pattern + # in the future to control source and target domain loader behavior + source_reg_tr = self.model.list_inner_product( + list_source_reg_tr, list_source_mu_tr + ) + # self.aconf.gamma_reg * loss_look_forward.sum() + loss = ( + loss_source_task.sum() + + source_reg_tr.sum() + + self.aconf.gamma_reg * loss_look_forward.sum() + ) + # + loss.backward() + # optimizer only optimize parameters of self.model, not inner_model + self.optimizer.step() + self.epo_loss_tr += loss.detach().item() + self.after_batch(epoch, ind_batch) + flag_stop = self.observer.update(epoch) # notify observer + return flag_stop diff --git a/domainlab/algos/trainers/train_visitor.py b/domainlab/algos/trainers/train_visitor.py deleted file mode 100644 index 196f2655f..000000000 --- a/domainlab/algos/trainers/train_visitor.py +++ /dev/null @@ -1,103 +0,0 @@ -""" -update hyper-parameters during training -""" -import warnings -import numpy as np -from domainlab.algos.trainers.train_basic import TrainerBasic - - -class TrainerVisitor(TrainerBasic): - """ - TrainerVisitor - """ - def set_scheduler(self, scheduler, total_steps, - flag_update_epoch=False, - flag_update_batch=False): - """ - set the warmup or anealing strategy - """ - self.hyper_scheduler = self.model.hyper_init(scheduler) - self.flag_update_hyper_per_epoch = flag_update_epoch - self.flag_update_hyper_per_batch = flag_update_batch - self.hyper_scheduler.set_steps(total_steps=total_steps) - - def after_batch(self, epoch, ind_batch): - if self.flag_update_hyper_per_batch: - self.model.hyper_update(epoch, self.hyper_scheduler) - return super().after_batch(epoch, ind_batch) - - def before_tr(self): - if self.hyper_scheduler is None: - warnings.warn("hyper-parameter scheduler not set, \ - going to use default Warmpup and epoch update") - self.set_scheduler(HyperSchedulerWarmup, - total_steps=self.aconf.warmup, - flag_update_epoch=True) - - def tr_epoch(self, epoch): - """ - update hyper-parameters only per epoch - """ - if self.flag_update_hyper_per_epoch: - self.model.hyper_update(epoch, self.hyper_scheduler) - return super().tr_epoch(epoch) - - def tr_batch(self, epoch, ind_batch): - """ - anneal hyper-parameter for each batch - """ - self.model.hyper_update(epoch*self.num_batches + ind_batch, self.hyper_scheduler) - return super().tr_epoch(epoch) - - -class HyperSchedulerWarmup(): - """ - HyperSchedulerWarmup - """ - def __init__(self, **kwargs): - self.dict_par_setpoint = kwargs - self.total_steps = None - - def set_steps(self, total_steps): - """ - set number of total_steps to gradually change optimization parameter - """ - self.total_steps = total_steps - - def warmup(self, par_setpoint, epoch): - """warmup. - start from a small value of par to ramp up the steady state value using - # total_steps - :param epoch: - """ - ratio = ((epoch+1) * 1.) / self.total_steps - list_par = [par_setpoint, par_setpoint * ratio] - par = min(list_par) - return par - - def __call__(self, epoch): - dict_rst = {} - for key, _ in self.dict_par_setpoint.items(): - dict_rst[key] = self.warmup(self.dict_par_setpoint[key], epoch) - return dict_rst - - -class HyperSchedulerAneal(HyperSchedulerWarmup): - """ - HyperSchedulerAneal - """ - def aneal(self, epoch, alpha): - """ - start from a small value of par to ramp up the steady state value using - number of total_steps - :param epoch: - """ - ratio = ((epoch+1) * 1.) / self.total_steps - denominator = (1. + np.exp(-10 * ratio)) - return float((2. / denominator - 1) * alpha) - - def __call__(self, epoch): - dict_rst = {} - for key, val in self.dict_par_setpoint.items(): - dict_rst[key] = self.aneal(epoch, val) - return dict_rst diff --git a/domainlab/algos/trainers/zoo_trainer.py b/domainlab/algos/trainers/zoo_trainer.py new file mode 100644 index 000000000..1cfa15a7f --- /dev/null +++ b/domainlab/algos/trainers/zoo_trainer.py @@ -0,0 +1,60 @@ +""" +select trainer +""" +from domainlab.algos.trainers.train_basic import TrainerBasic +from domainlab.algos.trainers.train_dial import TrainerDIAL +from domainlab.algos.trainers.train_hyper_scheduler import TrainerHyperScheduler +from domainlab.algos.trainers.train_matchdg import TrainerMatchDG +from domainlab.algos.trainers.train_mldg import TrainerMLDG +from domainlab.algos.trainers.train_fishr import TrainerFishr + + +class TrainerChainNodeGetter(object): + """ + Chain of Responsibility: node is named in pattern Trainer[XXX] where the string + after 'Trainer' is the name to be passed to args.trainer. + """ + + def __init__(self, str_trainer): + """__init__. + :param args: command line arguments + """ + self._list_str_trainer = None + if str_trainer is not None: + self._list_str_trainer = str_trainer.split("_") + self.request = self._list_str_trainer.pop(0) + else: + self.request = str_trainer + + def __call__(self, lst_candidates=None, default=None, lst_excludes=None): + """ + 1. construct the chain, filter out responsible node, + create heavy-weight business object + 2. hard code seems to be the best solution + """ + if lst_candidates is not None and self.request not in lst_candidates: + raise RuntimeError( + f"desired {self.request} is not supported \ + among {lst_candidates}" + ) + if default is not None and self.request is None: + self.request = default + if lst_excludes is not None and self.request in lst_excludes: + raise RuntimeError( + f"desired {self.request} is not supported among {lst_excludes}" + ) + + chain = TrainerBasic(None) + chain = TrainerDIAL(chain) + chain = TrainerMatchDG(chain) + chain = TrainerMLDG(chain) + chain = TrainerFishr(chain) + chain = TrainerHyperScheduler(chain) + node = chain.handle(self.request) + head = node + while self._list_str_trainer: + self.request = self._list_str_trainer.pop(0) + node2decorate = self.__call__(lst_candidates, default, lst_excludes) + head.extend(node2decorate) + head = node2decorate + return node diff --git a/domainlab/algos/utils.py b/domainlab/algos/utils.py new file mode 100644 index 000000000..1c36f29c6 --- /dev/null +++ b/domainlab/algos/utils.py @@ -0,0 +1,13 @@ +""" +network builder utils +""" +from torch import nn + + +def split_net_feat_last(net): + """ + split a pytorch module into feature extractor and last layer + """ + net_classifier = list(net.children())[-1] + net_invar_feat = nn.Sequential(*(list(net.children())[:-1])) + return net_invar_feat, net_classifier diff --git a/domainlab/algos/zoo_algos.py b/domainlab/algos/zoo_algos.py index 8e7915d17..e067c1326 100644 --- a/domainlab/algos/zoo_algos.py +++ b/domainlab/algos/zoo_algos.py @@ -1,27 +1,35 @@ +""" +chain of responsibility pattern for algorithm selection +""" +from domainlab.algos.builder_api_model import NodeAlgoBuilderAPIModel from domainlab.algos.builder_dann import NodeAlgoBuilderDANN -from domainlab.algos.builder_jigen1 import NodeAlgoBuilderJiGen -from domainlab.algos.builder_deepall import NodeAlgoBuilderDeepAll -from domainlab.algos.builder_dial import NodeAlgoBuilderDeepAll_DIAL from domainlab.algos.builder_diva import NodeAlgoBuilderDIVA +from domainlab.algos.builder_erm import NodeAlgoBuilderERM from domainlab.algos.builder_hduva import NodeAlgoBuilderHDUVA -from domainlab.algos.builder_matchdg import NodeAlgoBuilderMatchDG -from domainlab.compos.pcr.request import RequestArgs2ExpCmd +from domainlab.algos.builder_jigen1 import NodeAlgoBuilderJiGen from domainlab.utils.u_import import import_path -class AlgoBuilderChainNodeGetter(object): +class AlgoBuilderChainNodeGetter: """ 1. Hardcoded chain 3. Return selected node """ - def __init__(self, args): - self.request = RequestArgs2ExpCmd(args)() - self.args = args + + def __init__(self, model, apath): + self.model = model + self.apath = apath + # + self._list_str_model = model.split("_") + self.model = self._list_str_model.pop(0) def register_external_node(self, chain): - if self.args.apath is None: + """ + if the user specify an external python file to implement the algorithm + """ + if self.apath is None: return chain - node_module = import_path(self.args.apath) + node_module = import_path(self.apath) node_fun = node_module.get_node_na() # @FIXME: build_node API need newchain = node_fun(chain) return newchain @@ -32,12 +40,17 @@ def __call__(self): 2. hard code seems to be the best solution """ chain = NodeAlgoBuilderDIVA(None) - chain = NodeAlgoBuilderDeepAll(chain) - chain = NodeAlgoBuilderDeepAll_DIAL(chain) + chain = NodeAlgoBuilderERM(chain) chain = NodeAlgoBuilderDANN(chain) chain = NodeAlgoBuilderJiGen(chain) chain = NodeAlgoBuilderHDUVA(chain) - chain = NodeAlgoBuilderMatchDG(chain) + chain = NodeAlgoBuilderAPIModel(chain) chain = self.register_external_node(chain) - node = chain.handle(self.request) + node = chain.handle(self.model) + head = node + while self._list_str_model: + self.model = self._list_str_model.pop(0) + node2decorate = self.__call__() + head.extend(node2decorate) + head = node2decorate return node diff --git a/domainlab/arg_parser.py b/domainlab/arg_parser.py index 9423dd796..f8f78c28b 100644 --- a/domainlab/arg_parser.py +++ b/domainlab/arg_parser.py @@ -3,186 +3,355 @@ """ import argparse import warnings + import yaml -from domainlab.algos.compos.matchdg_args import add_args2parser_matchdg from domainlab.algos.trainers.args_dial import add_args2parser_dial -from domainlab.models.args_vae import add_args2parser_vae +from domainlab.algos.trainers.compos.matchdg_args import add_args2parser_matchdg from domainlab.models.args_jigen import add_args2parser_jigen +from domainlab.models.args_vae import add_args2parser_vae +from domainlab.utils.logger import Logger def mk_parser_main(): """ Args for command line definition """ - parser = argparse.ArgumentParser(description='DomainLab') - - parser.add_argument('-c', "--config", default=None, - help="load YAML configuration", dest="config_file", - type=argparse.FileType(mode='r')) - - parser.add_argument('--lr', type=float, default=1e-4, - help='learning rate') - - parser.add_argument('--gamma_reg', type=float, default=0.1, - help='weight of regularization loss') - - parser.add_argument('--es', type=int, default=10, - help='early stop steps') - - parser.add_argument('--seed', type=int, default=0, - help='random seed (default: 0)') - - parser.add_argument('--nocu', action='store_true', default=False, - help='disables CUDA') - - parser.add_argument('--gen', action='store_true', default=False, - help='save generated images') - - parser.add_argument('--keep_model', action='store_true', default=False, - help='do not delete model at the end of training') - - parser.add_argument('--epos', default=2, type=int, - help='maximum number of epochs') - - parser.add_argument('--epo_te', default=1, type=int, - help='test performance per {} epochs') - - parser.add_argument('--debug', action='store_true', default=False) - parser.add_argument('--dmem', action='store_true', default=False) - parser.add_argument('--no_dump', action='store_true', default=False, - help='suppress saving the confusion matrix') - - parser.add_argument('--trainer', type=str, default=None, - help='specify which trainer to use') - - parser.add_argument('--out', type=str, default="zoutput", - help='absolute directory to store outputs') - - parser.add_argument('--dpath', type=str, default="zdpath", - help="path for storing downloaded dataset") - - parser.add_argument('--tpath', type=str, default=None, - help="path for custom task, should implement \ - get_task function") - - parser.add_argument('--npath', type=str, default=None, - help="path of custom neural network for feature \ - extraction") - - parser.add_argument('--npath_dom', type=str, default=None, - help="path of custom neural network for feature \ - extraction") - - parser.add_argument('--npath_argna2val', action='append', - help="specify new arguments and their value \ + parser = argparse.ArgumentParser(description="DomainLab") + + parser.add_argument( + "-c", + "--config", + default=None, + help="load YAML configuration", + dest="config_file", + type=argparse.FileType(mode="r"), + ) + + parser.add_argument("--lr", type=float, default=1e-4, help="learning rate") + + parser.add_argument( + "--gamma_reg", type=float, default=0.1, help="weight of regularization loss" + ) + + parser.add_argument("--es", type=int, default=1, help="early stop steps") + + parser.add_argument("--seed", type=int, default=0, help="random seed (default: 0)") + + parser.add_argument( + "--nocu", action="store_true", default=False, help="disables CUDA" + ) + + parser.add_argument( + "--device", type=str, default=None, help="device name default None" + ) + + parser.add_argument( + "--gen", action="store_true", default=False, help="save generated images" + ) + + parser.add_argument( + "--keep_model", + action="store_true", + default=False, + help="do not delete model at the end of training", + ) + + parser.add_argument("--epos", default=2, type=int, help="maximum number of epochs") + + parser.add_argument( + "--epos_min", default=0, type=int, help="maximum number of epochs" + ) + + parser.add_argument( + "--epo_te", default=1, type=int, help="test performance per {} epochs" + ) + + parser.add_argument( + "-w", + "--warmup", + type=int, + default=100, + help="number of epochs for hyper-parameter warm-up. \ + Set to 0 to turn warmup off.", + ) + + parser.add_argument("--debug", action="store_true", default=False) + parser.add_argument("--dmem", action="store_true", default=False) + parser.add_argument( + "--no_dump", + action="store_true", + default=False, + help="suppress saving the confusion matrix", + ) + + parser.add_argument( + "--trainer", type=str, default=None, help="specify which trainer to use" + ) + + parser.add_argument( + "--out", type=str, default="zoutput", help="absolute directory to store outputs" + ) + + parser.add_argument( + "--dpath", + type=str, + default="zdpath", + help="path for storing downloaded dataset", + ) + + parser.add_argument( + "--tpath", + type=str, + default=None, + help="path for custom task, should implement \ + get_task function", + ) + + parser.add_argument( + "--npath", + type=str, + default=None, + help="path of custom neural network for feature \ + extraction", + ) + + parser.add_argument( + "--npath_dom", + type=str, + default=None, + help="path of custom neural network for feature \ + extraction", + ) + + parser.add_argument( + "--npath_argna2val", + action="append", + help="specify new arguments and their value \ e.g. '--npath_argna2val my_custom_arg_na \ --npath_argna2val xx/yy/zz.py', additional \ - pairs can be appended") + pairs can be appended", + ) - parser.add_argument('--nname_argna2val', action='append', - help="specify new arguments and their values \ + parser.add_argument( + "--nname_argna2val", + action="append", + help="specify new arguments and their values \ e.g. '--nname_argna2val my_custom_network_arg_na \ --nname_argna2val alexnet', additional pairs \ - can be appended") - - parser.add_argument('--nname', type=str, default=None, - help="name of custom neural network for feature \ - extraction of classification") - - parser.add_argument('--nname_dom', type=str, default=None, - help="name of custom neural network for feature \ - extraction of domain") - - parser.add_argument('--apath', type=str, default=None, - help="path for custom AlgorithmBuilder") - - parser.add_argument('--exptag', type=str, default="exptag", - help='tag as prefix of result aggregation file name \ - e.g. git hash for reproducibility') - - parser.add_argument('--aggtag', type=str, default="aggtag", - help='tag in each line of result aggregation file \ - e.g., to specify potential different configurations') - - parser.add_argument('--msel', type=str, default=None, - help='model selection: val, elbo, recon, the \ + can be appended", + ) + + parser.add_argument( + "--nname", + type=str, + default=None, + help="name of custom neural network for feature \ + extraction of classification", + ) + + parser.add_argument( + "--nname_dom", + type=str, + default=None, + help="name of custom neural network for feature \ + extraction of domain", + ) + + parser.add_argument( + "--apath", type=str, default=None, help="path for custom AlgorithmBuilder" + ) + + parser.add_argument( + "--exptag", + type=str, + default="exptag", + help="tag as prefix of result aggregation file name \ + e.g. git hash for reproducibility", + ) + + parser.add_argument( + "--aggtag", + type=str, + default="aggtag", + help="tag in each line of result aggregation file \ + e.g., to specify potential different configurations", + ) + + parser.add_argument( + "--agg_partial_bm", + type=str, + default=None, + dest="bm_dir", + help="Aggregates and plots partial data of a snakemake \ + benchmark. Requires the benchmark config file. \ + Other arguments will be ignored.", + ) + + parser.add_argument( + "--gen_plots", + type=str, + default=None, + dest="plot_data", + help="plots the data of a snakemake benchmark. " + "Requires the results.csv file" + "and an output file (specify by --outp_file," + "default is zoutput/benchmarks/shell_benchmark). " + "Other arguments will be ignored.", + ) + + parser.add_argument( + "--outp_dir", + type=str, + default="zoutput/benchmarks/shell_benchmark", + dest="outp_dir", + help="outpus file for the plots when creating them" + "using --gen_plots. " + "Default is zoutput/benchmarks/shell_benchmark", + ) + + parser.add_argument( + "--param_idx", + type=bool, + default=True, + dest="param_idx", + help="True: parameter index is used in the " + "pots generated with --gen_plots." + "False: parameter name is used." + "Default is True.", + ) + + parser.add_argument( + "--msel", + choices=["val", "loss_tr"], + default="val", + help="model selection for early stop: val, loss_tr, recon, the \ elbo and recon only make sense for vae models,\ - will be ignored by other methods') - - parser.add_argument('--aname', metavar="an", type=str, - default=None, - help='algorithm name') - - parser.add_argument('--acon', metavar="ac", type=str, default=None, - help='algorithm configuration name, (default None)') - - parser.add_argument('--task', metavar="ta", type=str, - help='task name') - - arg_group_task = parser.add_argument_group('task args') - - arg_group_task.add_argument('--bs', type=int, default=100, - help='loader batch size for mixed domains') - - arg_group_task.add_argument('--split', type=float, default=0, - help='proportion of training, a value between \ - 0 and 1, 0 means no train-validation split') - - arg_group_task.add_argument('--te_d', nargs='*', default=None, - help='test domain names separated by single space, \ - will be parsed to be list of strings') - - arg_group_task.add_argument('--tr_d', nargs='*', default=None, - help='training domain names separated by \ + will be ignored by other methods", + ) + + parser.add_argument( + "--model", metavar="an", type=str, default=None, help="algorithm name" + ) + + parser.add_argument( + "--acon", + metavar="ac", + type=str, + default=None, + help="algorithm configuration name, (default None)", + ) + + parser.add_argument("--task", metavar="ta", type=str, help="task name") + + arg_group_task = parser.add_argument_group("task args") + + arg_group_task.add_argument( + "--bs", type=int, default=100, help="loader batch size for mixed domains" + ) + + arg_group_task.add_argument( + "--split", + type=float, + default=0, + help="proportion of training, a value between \ + 0 and 1, 0 means no train-validation split", + ) + + arg_group_task.add_argument( + "--te_d", + nargs="*", + default=None, + help="test domain names separated by single space, \ + will be parsed to be list of strings", + ) + + arg_group_task.add_argument( + "--tr_d", + nargs="*", + default=None, + help="training domain names separated by \ single space, will be parsed to be list of \ strings; if not provided then all available \ domains that are not assigned to \ - the test set will be used as training domains') - - arg_group_task.add_argument('--san_check', action='store_true', default=False, - help='save images from the dataset as a sanity check') - - arg_group_task.add_argument('--san_num', type=int, default=8, - help='number of images to be dumped for the sanity check') + the test set will be used as training domains", + ) + + arg_group_task.add_argument( + "--san_check", + action="store_true", + default=False, + help="save images from the dataset as a sanity check", + ) + + arg_group_task.add_argument( + "--san_num", + type=int, + default=8, + help="number of images to be dumped for the sanity check", + ) + + arg_group_task.add_argument( + "--loglevel", type=str, default="DEBUG", help="sets the loglevel of the logger" + ) # args for variational auto encoder - arg_group_vae = parser.add_argument_group('vae') + arg_group_vae = parser.add_argument_group("vae") arg_group_vae = add_args2parser_vae(arg_group_vae) - arg_group_matchdg = parser.add_argument_group('matchdg') + arg_group_matchdg = parser.add_argument_group("matchdg") arg_group_matchdg = add_args2parser_matchdg(arg_group_matchdg) - arg_group_jigen = parser.add_argument_group('jigen') + arg_group_jigen = parser.add_argument_group("jigen") arg_group_jigen = add_args2parser_jigen(arg_group_jigen) - args_group_dial = parser.add_argument_group('dial') + args_group_dial = parser.add_argument_group("dial") args_group_dial = add_args2parser_dial(args_group_dial) return parser +def apply_dict_to_args(args, data: dict, extend=False): + """ + Tries to apply the data to the args dict of DomainLab. + Unknown keys are silently ignored as long as + extend is not set. + """ + arg_dict = args.__dict__ + for key, value in data.items(): + if (key in arg_dict) or extend: + if isinstance(value, list): + cur_val = arg_dict.get(key, None) + if not isinstance(cur_val, list): + if cur_val is not None: + raise RuntimeError( + f"input dictionary value is list, \ + however, in DomainLab args, we have {cur_val}, \ + going to overrite to list" + ) + arg_dict[key] = [] # if args_dict[key] is None, cast it into a list + # domainlab will take care of it if this argument can not be a list + arg_dict[key].extend(value) # args_dict[key] is already a list + # keep existing values for the list arg_dct[key] + else: + # over-write existing value + arg_dict[key] = value + else: + raise ValueError("Unsupported key: ", key) + + def parse_cmd_args(): """ get args from command line """ parser = mk_parser_main() args = parser.parse_args() + logger = Logger.get_logger(logger_name="main_out_logger", loglevel=args.loglevel) if args.config_file: - data = yaml.safe_load(args.config_file) - delattr(args, 'config_file') - arg_dict = args.__dict__ - - for key in data: - if key not in arg_dict: - raise ValueError("The key is not supported: ", key) - - for key, value in data.items(): - if isinstance(value, list): - arg_dict[key].extend(value) - else: - arg_dict[key] = value + delattr(args, "config_file") + apply_dict_to_args(args, data) - if args.acon is None: - print("\n\n") + if args.acon is None and args.bm_dir is None: + logger.warn("\n\n") + logger.warn("no algorithm conf specified, going to use default") + logger.warn("\n\n") warnings.warn("no algorithm conf specified, going to use default") - print("\n\n") return args diff --git a/domainlab/cli.py b/domainlab/cli.py new file mode 100644 index 000000000..082287e0e --- /dev/null +++ b/domainlab/cli.py @@ -0,0 +1,26 @@ +""" +command-line interface (CLI) for the domainlab package +""" + +from domainlab.arg_parser import parse_cmd_args +from domainlab.exp.exp_cuda_seed import set_seed # reproducibility +from domainlab.exp.exp_main import Exp +from domainlab.exp_protocol import aggregate_results +from domainlab.utils.generate_benchmark_plots import gen_benchmark_plots + + +def domainlab_cli(): + """ + Function used to run domainlab as a command line tool for the package installed with pip. + """ + args = parse_cmd_args() + if args.bm_dir: + aggregate_results.agg_main(args.bm_dir) + elif args.plot_data is not None: + gen_benchmark_plots( + args.plot_data, args.outp_dir, use_param_index=args.param_idx + ) + else: + set_seed(args.seed) + exp = Exp(args=args) + exp.execute() diff --git a/domainlab/compos/a_nn_builder.py b/domainlab/compos/a_nn_builder.py index 59c3589fe..1784c3384 100644 --- a/domainlab/compos/a_nn_builder.py +++ b/domainlab/compos/a_nn_builder.py @@ -13,6 +13,7 @@ class AbstractFeatExtractNNBuilderChainNode(AbstractChainNodeHandler): avoid override the initializer so that node construction is always light weight. """ + def __init__(self, successor_node): """__init__. @@ -22,8 +23,16 @@ def __init__(self, successor_node): super().__init__(successor_node) @store_args - def init_business(self, dim_out, args, i_c=None, i_h=None, i_w=None, - flag_pretrain=None, remove_last_layer=False): + def init_business( + self, + dim_out, + args, + i_c=None, + i_h=None, + i_w=None, + flag_pretrain=None, + remove_last_layer=False, + ): """ initialize **and** return the heavy weight business object for doing the real job diff --git a/domainlab/compos/builder_nn_alex.py b/domainlab/compos/builder_nn_alex.py index 1f38a53d5..a030febf1 100644 --- a/domainlab/compos/builder_nn_alex.py +++ b/domainlab/compos/builder_nn_alex.py @@ -7,14 +7,17 @@ class NodeFeatExtractNNBuilderAlex(AbstractFeatExtractNNBuilderChainNode): """NodeFeatExtractNNBuilderAlex. Uniform interface to return AlexNet and other neural network as feature extractor from torchvision or external python file""" - def init_business(self, dim_out, args, i_c=None, i_h=None, i_w=None, - remove_last_layer=False, flag_pretrain=True): + + def init_business( + self, dim_out, args, isize=None, remove_last_layer=False, flag_pretrain=True + ): """ initialize **and** return the heavy weight business object for doing the real job :param request: subclass can override request object to be string or function :return: the constructed service object + i_size is not used at all in this class """ if not remove_last_layer: self.net_feat_extract = Alex4DeepAll(flag_pretrain, dim_out) @@ -29,4 +32,5 @@ def is_myjob(self, args): """ arg_name = getattr(args, arg_name4net) return arg_name == arg_val + return NodeFeatExtractNNBuilderAlex diff --git a/domainlab/compos/builder_nn_conv_bn_relu_2.py b/domainlab/compos/builder_nn_conv_bn_relu_2.py index d2e140f13..0238595a2 100644 --- a/domainlab/compos/builder_nn_conv_bn_relu_2.py +++ b/domainlab/compos/builder_nn_conv_bn_relu_2.py @@ -2,8 +2,7 @@ from domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 import NetConvBnReluPool2L -def mkNodeFeatExtractNNBuilderNameConvBnRelu2(arg_name4net, arg_val, - conv_stride): +def mkNodeFeatExtractNNBuilderNameConvBnRelu2(arg_name4net, arg_val, conv_stride): """mkNodeFeatExtractNNBuilderNameConvBnRelu2. In chain of responsibility selection of neural network, reuse code to add more possibilities of neural network of the same family. @@ -14,18 +13,19 @@ def mkNodeFeatExtractNNBuilderNameConvBnRelu2(arg_name4net, arg_val, :param i_h: :param i_w: """ - class _NodeFeatExtractNNBuilderConvBnRelu2L( - AbstractFeatExtractNNBuilderChainNode): + + class _NodeFeatExtractNNBuilderConvBnRelu2L(AbstractFeatExtractNNBuilderChainNode): """NodeFeatExtractNNBuilderConvBnRelu2L.""" - def init_business(self, dim_out, args, i_c, i_h, i_w, - flag_pretrain=None, remove_last_layer=False): + def init_business( + self, dim_out, args, isize, flag_pretrain=None, remove_last_layer=False + ): """ :param flag_pretrain """ self.net_feat_extract = NetConvBnReluPool2L( - i_c=i_c, i_h=i_h, i_w=i_w, - conv_stride=conv_stride, dim_out_h=dim_out) + isize=isize, conv_stride=conv_stride, dim_out_h=dim_out + ) return self.net_feat_extract def is_myjob(self, args): @@ -35,4 +35,5 @@ def is_myjob(self, args): """ arg_name = getattr(args, arg_name4net) return arg_name == arg_val + return _NodeFeatExtractNNBuilderConvBnRelu2L diff --git a/domainlab/compos/builder_nn_external_from_file.py b/domainlab/compos/builder_nn_external_from_file.py index 35695ebf3..0d0161d19 100644 --- a/domainlab/compos/builder_nn_external_from_file.py +++ b/domainlab/compos/builder_nn_external_from_file.py @@ -1,6 +1,7 @@ from domainlab.compos.a_nn_builder import AbstractFeatExtractNNBuilderChainNode -from domainlab.utils.u_import_net_module import \ - build_external_obj_net_module_feat_extract +from domainlab.utils.u_import_net_module import ( + build_external_obj_net_module_feat_extract, +) def mkNodeFeatExtractNNBuilderExternFromFile(arg_name_net_path): @@ -9,14 +10,17 @@ def mkNodeFeatExtractNNBuilderExternFromFile(arg_name_net_path): for diva, there can be class feature extractor and domain feature extractor """ + class _LNodeFeatExtractNNBuilderExternFromFile( - AbstractFeatExtractNNBuilderChainNode): + AbstractFeatExtractNNBuilderChainNode + ): """LNodeFeatExtractNNBuilderExternFromFile. Local class to return """ - def init_business(self, dim_out, args, flag_pretrain, - remove_last_layer, - i_c=None, i_h=None, i_w=None): + + def init_business( + self, dim_out, args, flag_pretrain, remove_last_layer, isize=None + ): """ initialize **and** return the heavy weight business object for doing the real job @@ -26,12 +30,13 @@ def init_business(self, dim_out, args, flag_pretrain, """ pyfile4net = getattr(args, arg_name_net_path) net = build_external_obj_net_module_feat_extract( - pyfile4net, dim_out, remove_last_layer) + pyfile4net, dim_out, remove_last_layer + ) return net def is_myjob(self, args): - """is_myjob. - """ + """is_myjob.""" pyfile4net = getattr(args, arg_name_net_path) return pyfile4net is not None + return _LNodeFeatExtractNNBuilderExternFromFile diff --git a/domainlab/compos/exp/exp_main.py b/domainlab/compos/exp/exp_main.py deleted file mode 100755 index 04d1601b7..000000000 --- a/domainlab/compos/exp/exp_main.py +++ /dev/null @@ -1,100 +0,0 @@ -import datetime -import os -from torch.utils.data import Subset -import torch.utils.data as data_utils -import numpy as np - -from domainlab.algos.zoo_algos import AlgoBuilderChainNodeGetter -from domainlab.compos.exp.exp_utils import AggWriter -from domainlab.tasks.zoo_tasks import TaskChainNodeGetter -from domainlab.dsets.utils_data import plot_ds - -os.environ['CUDA_LAUNCH_BLOCKING'] = "1" # debug - - -class Exp(): - """ - Exp is combination of Task, Algorithm, and Configuration (including random seed) - """ - def __init__(self, args, task=None, visitor=AggWriter): - """ - :param args: - :param task: - """ - self.task = task - if task is None: - self.task = TaskChainNodeGetter(args)() - if args.san_check: - self.dataset_sanity_check(args, args.san_num) - self.task.init_business(args) - self.args = args - self.visitor = visitor(self) - algo_builder = AlgoBuilderChainNodeGetter(self.args)() # request - self.trainer = algo_builder.init_business(self) - self.epochs = self.args.epos - self.epoch_counter = 1 - - def execute(self): - """ - train model - check performance by loading persisted model - """ - t_0 = datetime.datetime.now() - print('\n Experiment start at :', str(t_0)) - t_c = t_0 - self.trainer.before_tr() - for epoch in range(1, self.epochs + 1): - t_before_epoch = t_c - flag_stop = self.trainer.tr_epoch(epoch) - t_c = datetime.datetime.now() - print(f"epoch: {epoch} ", - "now: ", str(t_c), - "epoch time: ", t_c - t_before_epoch, - "used: ", t_c - t_0, - "model: ", self.visitor.model_name) - # current time, time since experiment start, epoch time - if flag_stop: - self.epoch_counter = epoch - break - if epoch == self.epochs: - self.epoch_counter = self.epochs - else: - self.epoch_counter += 1 - print("Experiment finished at epoch:", self.epoch_counter, - "with time:", t_c - t_0, "at", t_c) - self.trainer.post_tr() - - def dataset_sanity_check(self, args, sample_num): - """ - when we load data from folder or a file listing the path of observations, - we want to check if the file we loaded are in accordance with our expectations - This function dump a subsample of the dataset into hierarchical folder structure. - """ - self.task.init_business(args) - f_name = os.path.join(args.out, 'Dset_extraction', self.task.task_name) - - # for each domain do... - for domain in self.task.get_list_domains(): - # generate a dataset for each domain - d_dataset = self.task.get_dset_by_domain(args, domain)[0] - - # for each class do... - for class_num in range(len(self.task.list_str_y)): - num_of_samples = 0 - loader_domain = data_utils.DataLoader(d_dataset, batch_size=1, shuffle=False) - domain_targets = [] - for num, (_, lab, *_) in enumerate(loader_domain): - if int(np.argmax(lab[0])) == class_num: - domain_targets.append(num) - num_of_samples += 1 - if sample_num == num_of_samples: - break - - class_dataset = Subset(d_dataset, domain_targets) - os.makedirs(f_name + '/' + str(domain), exist_ok=True) - plot_ds( - class_dataset, - f_name + '/' + str(domain) + '/' + - str(self.task.list_str_y[class_num]) + '.jpg', - batchsize=sample_num - ) diff --git a/domainlab/compos/nn_zoo/net_adversarial.py b/domainlab/compos/nn_zoo/net_adversarial.py index f90821ec9..5ed11c882 100644 --- a/domainlab/compos/nn_zoo/net_adversarial.py +++ b/domainlab/compos/nn_zoo/net_adversarial.py @@ -13,6 +13,7 @@ class AutoGradFunReverseMultiply(Function): https://pytorch.org/docs/stable/autograd.html https://pytorch.org/docs/stable/notes/extending.html#extending-autograd """ + @staticmethod def forward(ctx, x, alpha): ctx.alpha = alpha diff --git a/domainlab/compos/nn_zoo/net_classif.py b/domainlab/compos/nn_zoo/net_classif.py index da406490c..7ab1aee22 100644 --- a/domainlab/compos/nn_zoo/net_classif.py +++ b/domainlab/compos/nn_zoo/net_classif.py @@ -6,6 +6,7 @@ class ClassifDropoutReluLinear(nn.Module): """first apply dropout, then relu, then linearly fully connected, without activation""" + def __init__(self, z_dim, target_dim): """ :param z_dim: diff --git a/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.py b/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.py index 05f11a96a..c03cf6135 100644 --- a/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.py +++ b/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.py @@ -17,8 +17,7 @@ def mk_conv_bn_relu_pool(i_channel, conv_stride=1, max_pool_stride=2): :param max_pool_stride: """ conv_net = nn.Sequential( - nn.Conv2d(i_channel, 32, kernel_size=5, - stride=conv_stride, bias=False), + nn.Conv2d(i_channel, 32, kernel_size=5, stride=conv_stride, bias=False), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(2, stride=max_pool_stride), @@ -33,13 +32,13 @@ def mk_conv_bn_relu_pool(i_channel, conv_stride=1, max_pool_stride=2): class NetConvBnReluPool2L(nn.Module): - def __init__(self, i_c, i_h, i_w, conv_stride, dim_out_h): + def __init__(self, isize, conv_stride, dim_out_h): """ :param dim_out_h: """ super().__init__() + i_c, i_h, i_w = isize self.conv_net = mk_conv_bn_relu_pool(i_c, conv_stride) - ### self.hdim = get_flat_dim(self.conv_net, i_c, i_h, i_w) self.layer_last = nn.Linear(self.hdim, dim_out_h) @@ -47,8 +46,10 @@ def forward(self, tensor_x): """ :param tensor_x: image """ - conv_out = self.conv_net(tensor_x) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) - flat = conv_out.view(-1, self.hdim) # 1024 = 64 * (4*4) + conv_out = self.conv_net( + tensor_x + ) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) + flat = conv_out.view(-1, self.hdim) # 1024 = 64 * (4*4) hidden = self.layer_last(flat) return hidden @@ -56,15 +57,17 @@ def forward(self, tensor_x): class NetConvDense(nn.Module): """ - For direct topic inference - - For custom deep_all, which is extracting the path of VAE from encoder + - For custom erm, which is extracting the path of VAE from encoder until classifier. note in encoder, there is extra layer of hidden to mean and scale, in this component, it is replaced with another hidden layer. """ - def __init__(self, i_c, i_h, i_w, conv_stride, dim_out_h, args, dense_layer=None): + + def __init__(self, isize, conv_stride, dim_out_h, args, dense_layer=None): """ :param dim_out_h: """ super().__init__() + i_c, i_h, i_w = isize self.conv_net = mk_conv_bn_relu_pool(i_c, conv_stride) ### self.hdim = get_flat_dim(self.conv_net, i_c, i_h, i_w) @@ -77,7 +80,9 @@ def forward(self, tensor_x): """ :param tensor_x: image """ - conv_out = self.conv_net(tensor_x) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) - flat = conv_out.view(-1, self.hdim) # 1024 = 64 * (4*4) + conv_out = self.conv_net( + tensor_x + ) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) + flat = conv_out.view(-1, self.hdim) # 1024 = 64 * (4*4) hidden = self.dense_layers(flat) return hidden diff --git a/domainlab/compos/nn_zoo/net_gated.py b/domainlab/compos/nn_zoo/net_gated.py index b0f9c5823..dd9e0999a 100644 --- a/domainlab/compos/nn_zoo/net_gated.py +++ b/domainlab/compos/nn_zoo/net_gated.py @@ -19,34 +19,67 @@ def forward(self, x): return h * g -#========================================================================== + +# ========================================================================== class GatedConv2d(nn.Module): - def __init__(self, input_channels, output_channels, kernel_size, stride, padding, dilation=1, activation=None): + def __init__( + self, + input_channels, + output_channels, + kernel_size, + stride, + padding, + dilation=1, + activation=None, + ): super(GatedConv2d, self).__init__() self.activation = activation self.sigmoid = nn.Sigmoid() - self.h = nn.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation) - self.g = nn.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation) + self.h = nn.Conv2d( + input_channels, output_channels, kernel_size, stride, padding, dilation + ) + self.g = nn.Conv2d( + input_channels, output_channels, kernel_size, stride, padding, dilation + ) def forward(self, x): if self.activation is None: h = self.h(x) else: - h = self.activation( self.h( x ) ) + h = self.activation(self.h(x)) - g = self.sigmoid( self.g( x ) ) + g = self.sigmoid(self.g(x)) return h * g -#============================================================================== + +# ============================================================================== class Conv2d(nn.Module): - def __init__(self, input_channels, output_channels, kernel_size, stride, padding, dilation=1, activation=None, bias=True): + def __init__( + self, + input_channels, + output_channels, + kernel_size, + stride, + padding, + dilation=1, + activation=None, + bias=True, + ): super(Conv2d, self).__init__() self.activation = activation - self.conv = nn.Conv2d(input_channels, output_channels, kernel_size, stride, padding, dilation, bias=bias) + self.conv = nn.Conv2d( + input_channels, + output_channels, + kernel_size, + stride, + padding, + dilation, + bias=bias, + ) def forward(self, x): h = self.conv(x) diff --git a/domainlab/compos/nn_zoo/nn.py b/domainlab/compos/nn_zoo/nn.py index c1d338e2d..85dd6849b 100644 --- a/domainlab/compos/nn_zoo/nn.py +++ b/domainlab/compos/nn_zoo/nn.py @@ -5,6 +5,7 @@ class LayerId(nn.Module): """ used to delete layers """ + def __init__(self): super().__init__() @@ -19,7 +20,10 @@ class DenseNet(nn.Module): """ (input)-dropout-linear-relu-dropout-linear-relu(output) """ - def __init__(self, input_flat_size, out_hidden_size=1024, last_feat_dim=4096, p_dropout=0.5): + + def __init__( + self, input_flat_size, out_hidden_size=1024, last_feat_dim=4096, p_dropout=0.5 + ): """ :param input_flat_size: :param out_hidden_size: diff --git a/domainlab/compos/nn_zoo/nn_alex.py b/domainlab/compos/nn_zoo/nn_alex.py index 865eda5f9..8a1e6339f 100644 --- a/domainlab/compos/nn_zoo/nn_alex.py +++ b/domainlab/compos/nn_zoo/nn_alex.py @@ -3,6 +3,7 @@ from domainlab.compos.nn_zoo.nn import LayerId from domainlab.compos.nn_zoo.nn_torchvision import NetTorchVisionBase +from domainlab.utils.logger import Logger class AlexNetBase(NetTorchVisionBase): @@ -37,30 +38,36 @@ class AlexNetBase(NetTorchVisionBase): ) ) """ + def fetch_net(self, flag_pretrain): - self.net_torchvision = torchvisionmodels.alexnet( - pretrained=flag_pretrain) + self.net_torchvision = torchvisionmodels.alexnet(pretrained=flag_pretrain) class Alex4DeepAll(AlexNetBase): """ change the last layer output of AlexNet to the dimension of the """ + def __init__(self, flag_pretrain, dim_y): super().__init__(flag_pretrain) if self.net_torchvision.classifier[6].out_features != dim_y: - print("original alex net out dim", self.net_torchvision.classifier[6].out_features) + logger = Logger.get_logger() + logger.info( + f"original alex net out dim " + f"{self.net_torchvision.classifier[6].out_features}" + ) num_ftrs = self.net_torchvision.classifier[6].in_features self.net_torchvision.classifier[6] = nn.Linear(num_ftrs, dim_y) - print("re-initialized to ", dim_y) + logger.info(f"re-initialized to {dim_y}") class AlexNetNoLastLayer(AlexNetBase): """ Change the last layer of AlexNet with identity layer, - the classifier from VAE can then have the same layer depth as deep_all + the classifier from VAE can then have the same layer depth as erm model so it is fair for comparison """ + def __init__(self, flag_pretrain): super().__init__(flag_pretrain) self.net_torchvision.classifier[6] = LayerId() diff --git a/domainlab/compos/nn_zoo/nn_torchvision.py b/domainlab/compos/nn_zoo/nn_torchvision.py index 870c02671..1cca73a43 100644 --- a/domainlab/compos/nn_zoo/nn_torchvision.py +++ b/domainlab/compos/nn_zoo/nn_torchvision.py @@ -1,10 +1,13 @@ import torch.nn as nn +from domainlab.utils.logger import Logger + class NetTorchVisionBase(nn.Module): """ fetch model from torchvision """ + def __init__(self, flag_pretrain): super().__init__() self.net_torchvision = None @@ -26,4 +29,5 @@ def show(self): """ for name, param in self.net_torchvision.named_parameters(): if param.requires_grad: - print("layers that will be optimized: \t", name) + logger = Logger.get_logger() + logger.info(f"layers that will be optimized: \t{name}") diff --git a/docs/build/html/.nojekyll b/domainlab/compos/pcr/__init__.py similarity index 100% rename from docs/build/html/.nojekyll rename to domainlab/compos/pcr/__init__.py diff --git a/domainlab/compos/pcr/p_chain_handler.py b/domainlab/compos/pcr/p_chain_handler.py index 661b92fab..31c428897 100644 --- a/domainlab/compos/pcr/p_chain_handler.py +++ b/domainlab/compos/pcr/p_chain_handler.py @@ -4,11 +4,14 @@ import abc +from domainlab.utils.logger import Logger + class Request4Chain(metaclass=abc.ABCMeta): """ define all available fields of request to ensure operation safety """ + @abc.abstractmethod def convert(self, obj): """ @@ -46,8 +49,10 @@ def __init__(self, success_node=None): :param success_node: successor chain node which implement the AbstractChainNodeHandler interface """ + self._task = None self._success_node = success_node self._parent_node = None + self.next_model = None if success_node is not None: success_node.set_parent(self) @@ -82,24 +87,26 @@ def handle(self, request): return self if self._success_node is not None: return self._success_node.handle(request) - err_msg = str(request) + " does not exist" - print("available options are") + err_msg = "option " + str(request) + " does not exist" + logger = Logger.get_logger() + logger.info(err_msg) + logger.info("available options are") self.print_options() raise NotImplementedError(err_msg) def print_options(self): - print(self.__class__.__name__) + logger = Logger.get_logger() + logger.info(str(self.__class__.__name__)) if self._parent_node is not None: self._parent_node.print_options() -class DummyBusiness(): +class DummyBusiness: message = "dummy business" class DummyChainNodeHandlerBeaver(AbstractChainNodeHandler): - """Dummy class to show how to inherit from Chain of Responsibility - """ + """Dummy class to show how to inherit from Chain of Responsibility""" def init_business(self, *kargs, **kwargs): return DummyBusiness() @@ -113,8 +120,7 @@ def is_myjob(self, request): class DummyChainNodeHandlerLazy(AbstractChainNodeHandler): - """Dummy class to show how to inherit from Chain of Responsibility - """ + """Dummy class to show how to inherit from Chain of Responsibility""" def init_business(self, *kargs, **kwargs): return DummyBusiness() diff --git a/domainlab/compos/pcr/request.py b/domainlab/compos/pcr/request.py index f883844f1..e3fe5ceee 100644 --- a/domainlab/compos/pcr/request.py +++ b/domainlab/compos/pcr/request.py @@ -1,16 +1,25 @@ from domainlab.utils.utils_class import store_args -class RequestVAEBuilderCHW(): +class RequestVAEBuilderCHW: @store_args def __init__(self, i_c, i_h, i_w, args): pass -class RequestTask(): +class RequestVAEBuilderNN: + """creates request when input does not come from command-line (args) but from test_exp file""" + + @store_args + def __init__(self, net_class_d, net_x, net_class_y, i_c, i_h, i_w): + """net_class_d, net_x and net_class_y are neural networks defined by the user""" + + +class RequestTask: """ Isolate args from Request object of chain of responsibility node for task """ + def __init__(self, args): self.args = args @@ -18,15 +27,16 @@ def __call__(self): return self.args.task -class RequestArgs2ExpCmd(): +class RequestArgs2ExpCmd: """ Isolate args from Request object of chain of responsibility node for experiment For example, args has field names which will couple with experiment class, this request class also serves as isolation class or adaptation class """ + @store_args def __init__(self, args): self.args = args def __call__(self): - return self.args.aname + return self.args.model diff --git a/domainlab/compos/vae/__init__.py b/domainlab/compos/vae/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/domainlab/compos/vae/a_vae_builder.py b/domainlab/compos/vae/a_vae_builder.py index 4563268cd..7baef60a5 100644 --- a/domainlab/compos/vae/a_vae_builder.py +++ b/domainlab/compos/vae/a_vae_builder.py @@ -16,6 +16,7 @@ class AbstractVAEBuilderChainNode(AbstractChainNodeHandler): avoid override the initializer so that node construction is always light weight. """ + def __init__(self, successor_node): self.args = None self.zd_dim = None diff --git a/domainlab/compos/vae/c_vae_adaptor_model_recon.py b/domainlab/compos/vae/c_vae_adaptor_model_recon.py index f2d8d14df..b6f38cd16 100644 --- a/domainlab/compos/vae/c_vae_adaptor_model_recon.py +++ b/domainlab/compos/vae/c_vae_adaptor_model_recon.py @@ -5,12 +5,13 @@ """ -class AdaptorReconVAEXYD(): +class AdaptorReconVAEXYD: """ This adaptor couples intensively with the heavy-weight model class The model class can be refactored, we do want to use the trained old-version model, which we only need to change this adaptor class. """ + def __init__(self, model): self.model = model @@ -23,8 +24,7 @@ def cal_latent(self, x): we only need to change this method. :param x: """ - q_zd, _, q_zx, _, q_zy, _ = \ - self.model.encoder(x) + q_zd, _, q_zx, _, q_zy, _ = self.model.encoder(x) return q_zd, q_zx, q_zy def recon_ydx(self, zy, zd, zx, x): @@ -41,13 +41,11 @@ def recon_ydx(self, zy, zd, zx, x): return x_mean def cal_prior_zy(self, vec_y): - """ - """ + """ """ p_zy = self.model.net_p_zy(vec_y) return p_zy def cal_prior_zd(self, vec_d): - """ - """ + """ """ p_zd = self.model.net_p_zd(vec_d) return p_zd diff --git a/domainlab/compos/vae/c_vae_builder_classif.py b/domainlab/compos/vae/c_vae_builder_classif.py index 1616dd40f..3478193ef 100644 --- a/domainlab/compos/vae/c_vae_builder_classif.py +++ b/domainlab/compos/vae/c_vae_builder_classif.py @@ -5,8 +5,9 @@ """ from domainlab.compos.nn_zoo.net_classif import ClassifDropoutReluLinear from domainlab.compos.vae.a_vae_builder import AbstractVAEBuilderChainNode -from domainlab.compos.vae.compos.decoder_cond_prior import \ - LSCondPriorLinearBnReluLinearSoftPlus +from domainlab.compos.vae.compos.decoder_cond_prior import ( + LSCondPriorLinearBnReluLinearSoftPlus, +) class ChainNodeVAEBuilderClassifCondPrior(AbstractVAEBuilderChainNode): @@ -16,6 +17,7 @@ class ChainNodeVAEBuilderClassifCondPrior(AbstractVAEBuilderChainNode): - conditional prior 2. Bridge pattern: separate abstraction (vae model) and implementation) """ + def construct_classifier(self, input_dim, output_dim): """ classifier can be used to both classify class-label and domain-label diff --git a/domainlab/compos/vae/c_vae_recon.py b/domainlab/compos/vae/c_vae_recon.py index 0e65cbad3..50e2518db 100644 --- a/domainlab/compos/vae/c_vae_recon.py +++ b/domainlab/compos/vae/c_vae_recon.py @@ -8,19 +8,26 @@ from domainlab.compos.vae.c_vae_adaptor_model_recon import AdaptorReconVAEXYD -class ReconVAEXYD(): +class ReconVAEXYD: """ Adaptor is vital for data generation so this class can be decoupled from model class. The model class can be refactored, we do want to use the trained old-version model, which we only need to change adaptor class. """ + def __init__(self, model, na_adaptor=AdaptorReconVAEXYD): self.model = model self.adaptor = na_adaptor(self.model) - def recon(self, x, vec_y=None, vec_d=None, - sample_p_zy=False, sample_p_zd=False, - scalar_zx2fill=None): + def recon( + self, + x, + vec_y=None, + vec_d=None, + sample_p_zy=False, + sample_p_zd=False, + scalar_zx2fill=None, + ): """ common function """ @@ -44,7 +51,9 @@ def recon(self, x, vec_y=None, vec_d=None, if scalar_zx2fill is not None: recon_zx = torch.zeros_like(zx_loc_q) recon_zx = recon_zx.fill_(scalar_zx2fill) - str_type = "_".join([str_type, "__fill_zx_", str(scalar_zx2fill), "___"]) + str_type = "_".join( + [str_type, "__fill_zx_", str(scalar_zx2fill), "___"] + ) else: recon_zx = zx_loc_q str_type = "_".join([str_type, "__zx_q__"]) @@ -62,10 +71,18 @@ def recon(self, x, vec_y=None, vec_d=None, img_recon = self.adaptor.recon_ydx(recon_zy, recon_zd, recon_zx, x) return img_recon, str_type - def recon_cf(self, x, na_cf, dim_cf, device, - vec_y=None, vec_d=None, - zx2fill=None, - sample_p_zy=False, sample_p_zd=False): + def recon_cf( + self, + x, + na_cf, + dim_cf, + device, + vec_y=None, + vec_d=None, + zx2fill=None, + sample_p_zy=False, + sample_p_zd=False, + ): """ Countefactual reconstruction: :param na_cf: name of counterfactual, 'y' or 'd' @@ -79,10 +96,16 @@ def recon_cf(self, x, na_cf, dim_cf, device, label_cf = torch.zeros(batch_size, dim_cf).to(device) label_cf[:, i] = 1 if na_cf == "y": - img_recon_cf, str_type = self.recon(x, label_cf, vec_d, sample_p_zy, sample_p_zd, zx2fill) + img_recon_cf, str_type = self.recon( + x, label_cf, vec_d, sample_p_zy, sample_p_zd, zx2fill + ) elif na_cf == "d": - img_recon_cf, str_type = self.recon(x, vec_y, label_cf, sample_p_zy, sample_p_zd, zx2fill) + img_recon_cf, str_type = self.recon( + x, vec_y, label_cf, sample_p_zy, sample_p_zd, zx2fill + ) else: - raise RuntimeError("counterfactual image generation can only be 'y' or 'd'") + raise RuntimeError( + "counterfactual image generation can only be 'y' or 'd'" + ) list_recon_cf.append(img_recon_cf) return list_recon_cf, str_type diff --git a/domainlab/compos/vae/compos/__init__.py b/domainlab/compos/vae/compos/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv.py b/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv.py index 2065d88a5..2b0ff5421 100644 --- a/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv.py +++ b/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv.py @@ -10,12 +10,19 @@ class DecoderConcatLatentFcReshapeConv(nn.Module): Latent vector re-arranged to image-size directly, then convolute to get the textures of the original image """ - def __init__(self, z_dim, i_c, i_h, i_w, - cls_fun_nll_p_x, - net_fc_z2flat_img, - net_conv, - net_p_x_mean, - net_p_x_log_var): + + def __init__( + self, + z_dim, + i_c, + i_h, + i_w, + cls_fun_nll_p_x, + net_fc_z2flat_img, + net_conv, + net_p_x_mean, + net_p_x_log_var, + ): """ :param z_dim: :param list_im_chw: [channel, height, width] @@ -35,14 +42,18 @@ def cal_p_x_pars_loc_scale(self, vec_z): """ h_flat = self.net_fc_z2flat_img(vec_z) # reshape to image - h_img = h_flat.view(-1, self.list_im_chw[0], self.list_im_chw[1], self.list_im_chw[2]) + h_img = h_flat.view( + -1, self.list_im_chw[0], self.list_im_chw[1], self.list_im_chw[2] + ) h_img_conv = self.net_conv(h_img) # pixel must be positive: enforced by sigmoid activation x_mean = self.net_p_x_mean(h_img_conv) # .view(-1, np.prod(self.list_im_chw)) # remove the saturated part of sigmoid - x_mean = torch.clamp(x_mean, min=0.+1./512., max=1.-1./512.) + x_mean = torch.clamp(x_mean, min=0.0 + 1.0 / 512.0, max=1.0 - 1.0 / 512.0) # negative values - x_logvar = self.net_p_x_log_var(h_img_conv) # .view(-1, np.prod(self.list_im_chw)) + x_logvar = self.net_p_x_log_var( + h_img_conv + ) # .view(-1, np.prod(self.list_im_chw)) return x_mean, x_logvar def concat_ydx(self, zy, zd, zx): diff --git a/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv_gated_conv.py b/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv_gated_conv.py index 95561f40e..00fd57b5c 100644 --- a/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv_gated_conv.py +++ b/domainlab/compos/vae/compos/decoder_concat_vec_reshape_conv_gated_conv.py @@ -6,8 +6,9 @@ import torch.nn as nn from domainlab.compos.nn_zoo.net_gated import Conv2d, GatedConv2d, GatedDense -from domainlab.compos.vae.compos.decoder_concat_vec_reshape_conv import \ - DecoderConcatLatentFcReshapeConv +from domainlab.compos.vae.compos.decoder_concat_vec_reshape_conv import ( + DecoderConcatLatentFcReshapeConv, +) from domainlab.compos.vae.compos.decoder_losses import NLLPixelLogistic256 @@ -18,6 +19,7 @@ class DecoderConcatLatentFCReshapeConvGatedConv(DecoderConcatLatentFcReshapeConv Latent vector re-arranged to image-size directly, then convolute to get the textures of the original image """ + def __init__(self, z_dim, i_c, i_h, i_w): """ :param z_dim: @@ -26,9 +28,7 @@ def __init__(self, z_dim, i_c, i_h, i_w): """ list_im_chw = [i_c, i_h, i_w] cls_fun_nll_p_x = NLLPixelLogistic256 - net_fc_z2flat_img = nn.Sequential( - GatedDense(z_dim, np.prod(list_im_chw)) - ) + net_fc_z2flat_img = nn.Sequential(GatedDense(z_dim, np.prod(list_im_chw))) net_conv = nn.Sequential( # GatedConv2d @@ -43,13 +43,23 @@ def __init__(self, z_dim, i_c, i_h, i_w): # # hidden image to mean and variance of each pixel # stride(1) and kernel size 1, pad 0 - net_p_x_mean = Conv2d(64, list_im_chw[0], 1, 1, 0, - activation=nn.Sigmoid()) - net_p_x_log_var = Conv2d(64, list_im_chw[0], 1, 1, 0, - activation=nn.Hardtanh(min_val=-4.5, max_val=0.)) - super().__init__(z_dim, i_c, i_h, i_w, - cls_fun_nll_p_x, - net_fc_z2flat_img, - net_conv, - net_p_x_mean, - net_p_x_log_var) + net_p_x_mean = Conv2d(64, list_im_chw[0], 1, 1, 0, activation=nn.Sigmoid()) + net_p_x_log_var = Conv2d( + 64, + list_im_chw[0], + 1, + 1, + 0, + activation=nn.Hardtanh(min_val=-4.5, max_val=0.0), + ) + super().__init__( + z_dim, + i_c, + i_h, + i_w, + cls_fun_nll_p_x, + net_fc_z2flat_img, + net_conv, + net_p_x_mean, + net_p_x_log_var, + ) diff --git a/domainlab/compos/vae/compos/decoder_cond_prior.py b/domainlab/compos/vae/compos/decoder_cond_prior.py index bdb0301b5..d54d1d860 100644 --- a/domainlab/compos/vae/compos/decoder_cond_prior.py +++ b/domainlab/compos/vae/compos/decoder_cond_prior.py @@ -7,6 +7,7 @@ class LSCondPriorLinearBnReluLinearSoftPlus(nn.Module): """ Location-Scale: from hyper-prior to current layer prior distribution """ + def __init__(self, hyper_prior_dim, z_dim, hidden_dim=None): super().__init__() if hidden_dim is None: @@ -14,7 +15,8 @@ def __init__(self, hyper_prior_dim, z_dim, hidden_dim=None): self.net_linear_bn_relu = nn.Sequential( nn.Linear(hyper_prior_dim, self.hidden_dim, bias=False), nn.BatchNorm1d(self.hidden_dim), - nn.ReLU()) + nn.ReLU(), + ) self.fc_loc = nn.Sequential(nn.Linear(self.hidden_dim, z_dim)) # No activation, because latent code z variable can take both negative and positive value self.fc_scale = nn.Sequential(nn.Linear(self.hidden_dim, z_dim), nn.Softplus()) @@ -22,9 +24,9 @@ def __init__(self, hyper_prior_dim, z_dim, hidden_dim=None): # initialization torch.nn.init.xavier_uniform_(self.net_linear_bn_relu[0].weight) torch.nn.init.xavier_uniform_(self.fc_loc[0].weight) - self.fc_loc[0].bias.data.zero_() # No Bias + self.fc_loc[0].bias.data.zero_() # No Bias torch.nn.init.xavier_uniform_(self.fc_scale[0].weight) - self.fc_scale[0].bias.data.zero_() # No Bias + self.fc_scale[0].bias.data.zero_() # No Bias def forward(self, hyper_prior): """ diff --git a/domainlab/compos/vae/compos/decoder_losses.py b/domainlab/compos/vae/compos/decoder_losses.py index 5c0078c1e..7eccbc098 100644 --- a/domainlab/compos/vae/compos/decoder_losses.py +++ b/domainlab/compos/vae/compos/decoder_losses.py @@ -3,6 +3,8 @@ """ import torch +from domainlab import g_inst_component_loss_agg + class NLLPixelLogistic256(object): """ @@ -13,7 +15,8 @@ class NLLPixelLogistic256(object): c.d.f.(x_{i,j}+bin_size/scale) - c.d.f.(x_{i,j}) # https://github.com/openai/iaf/blob/master/tf_utils/distributions.py#L29 """ - def __init__(self, reduce_dims=(1, 2, 3), bin_size=1. / 256.): + + def __init__(self, reduce_dims=(1, 2, 3), bin_size=1.0 / 256.0): """ :param reduce_dims: """ @@ -30,12 +33,13 @@ def __call__(self, tensor, mean, logvar): """ scale = torch.exp(logvar) tensor = (torch.floor(tensor / self.bin_size) * self.bin_size - mean) / scale - cdf_plus = torch.sigmoid(tensor + self.bin_size/scale) + cdf_plus = torch.sigmoid(tensor + self.bin_size / scale) cdf_minus = torch.sigmoid(tensor) # negative log-likelihood for each pixel - log_logist_256 = - torch.log(cdf_plus - cdf_minus + 1.e-7) - nll = torch.sum(log_logist_256, dim=self.reduce_dims) + log_logist_256 = -torch.log(cdf_plus - cdf_minus + 1.0e-7) + # torch.Size([100, 3, 28, 28]) + nll = g_inst_component_loss_agg(log_logist_256, dim=self.reduce_dims) # NOTE: pixel NLL should always be summed # across the whole image of all channels # NOTE: result should be order 1 tensor of dim batch_size diff --git a/domainlab/compos/vae/compos/encoder.py b/domainlab/compos/vae/compos/encoder.py index 95164b8b1..b8d475324 100644 --- a/domainlab/compos/vae/compos/encoder.py +++ b/domainlab/compos/vae/compos/encoder.py @@ -6,8 +6,7 @@ import torch.distributions as dist import torch.nn as nn -from domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 import \ - mk_conv_bn_relu_pool +from domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 import mk_conv_bn_relu_pool from domainlab.compos.nn_zoo.nn import DenseNet from domainlab.compos.utils_conv_get_flat_dim import get_flat_dim @@ -17,7 +16,8 @@ class LSEncoderConvBnReluPool(nn.Module): Batch Normalization, Relu and Pooling. Softplus for scale """ - def __init__(self, z_dim, i_channel, i_h, i_w, conv_stride): + + def __init__(self, z_dim: int, i_channel, i_h, i_w, conv_stride): """ :param z_dim: nn.Sequential allows output dim to be zero. @@ -32,13 +32,13 @@ def __init__(self, z_dim, i_channel, i_h, i_w, conv_stride): self.i_h = i_h self.i_w = i_w - self.conv = mk_conv_bn_relu_pool(self.i_channel, - conv_stride=conv_stride) + self.conv = mk_conv_bn_relu_pool(self.i_channel, conv_stride=conv_stride) # conv-bn-relu-pool-conv-bn-relu-pool(no activation) self.flat_dim = get_flat_dim(self.conv, i_channel, i_h, i_w) self.fc_loc = nn.Sequential(nn.Linear(self.flat_dim, z_dim)) - self.fc_scale = nn.Sequential(nn.Linear(self.flat_dim, z_dim), - nn.Softplus()) # for scale calculation + self.fc_scale = nn.Sequential( + nn.Linear(self.flat_dim, z_dim), nn.Softplus() + ) # for scale calculation # initialization torch.nn.init.xavier_uniform_(self.fc_loc[0].weight) @@ -59,28 +59,23 @@ def forward(self, img): return q_zd, zd_q -class LSEncoderDense(nn.Module): +class LSEncoderLinear(nn.Module): """ Location-Scale Encoder with DenseNet as feature extractor Softplus for scale """ - def __init__(self, z_dim, dim_input, dim_h=4096): + + def __init__(self, z_dim, dim_input): """ :param z_dim: nn.Sequential allows output dim to be zero. So z_dim here can be set to be zero - :param i_channel: - :param i_h: - :param i_w: - :param conv_stride: """ super().__init__() - self.net_feat = DenseNet( - input_flat_size=dim_input, out_hidden_size=dim_h) - # conv-bn-relu-pool-conv-bn-relu-pool(no activation) - self.fc_loc = nn.Sequential(nn.Linear(dim_h, z_dim)) - self.fc_scale = nn.Sequential(nn.Linear(dim_h, z_dim), - nn.Softplus()) # for scale calculation + self.fc_loc = nn.Sequential(nn.Linear(dim_input, z_dim)) + self.fc_scale = nn.Sequential( + nn.Linear(dim_input, z_dim), nn.Softplus() + ) # for scale calculation # initialization torch.nn.init.xavier_uniform_(self.fc_loc[0].weight) @@ -88,11 +83,10 @@ def __init__(self, z_dim, dim_input, dim_h=4096): torch.nn.init.xavier_uniform_(self.fc_scale[0].weight) self.fc_scale[0].bias.data.zero_() - def forward(self, tensor_x): + def forward(self, hidden): """. - :param tensor_x: + :param hidden: """ - hidden = self.net_feat(tensor_x) zd_q_loc = self.fc_loc(hidden) zd_q_scale = self.fc_scale(hidden) + 1e-7 q_zd = dist.Normal(zd_q_loc, zd_q_scale) diff --git a/domainlab/compos/vae/compos/encoder_dirichlet.py b/domainlab/compos/vae/compos/encoder_dirichlet.py index 86b886c14..9862eea01 100644 --- a/domainlab/compos/vae/compos/encoder_dirichlet.py +++ b/domainlab/compos/vae/compos/encoder_dirichlet.py @@ -1,3 +1,4 @@ +import torch import torch.nn as nn from torch.distributions import Dirichlet @@ -7,19 +8,20 @@ class EncoderH2Dirichlet(nn.Module): hidden representation to Dirichlet Distribution """ - def __init__(self, dim_h, dim_topic, device): - """ - """ + def __init__(self, dim_topic, device): + """ """ super().__init__() - self.net_fc = nn.Linear(dim_h, dim_topic) self.layer_bn = nn.BatchNorm1d(dim_topic) + self.layer_concentration = nn.Softplus() self.device = device def forward(self, hidden): """ :param hidden: """ - alphas_batch = self.layer_bn(self.net_fc(hidden)).exp() - q_topic = Dirichlet(alphas_batch) + feat_bnorm = self.layer_bn(hidden) + # alphas_batch = torch.log(1 + feat_bnorm.exp()) + alphas_batch = self.layer_concentration(feat_bnorm) + q_topic = Dirichlet(alphas_batch + 1e-6) topic_q = q_topic.rsample().to(self.device) return q_topic, topic_q diff --git a/domainlab/compos/vae/compos/encoder_domain_topic.py b/domainlab/compos/vae/compos/encoder_domain_topic.py index b4693afbc..57674871e 100644 --- a/domainlab/compos/vae/compos/encoder_domain_topic.py +++ b/domainlab/compos/vae/compos/encoder_domain_topic.py @@ -1,20 +1,17 @@ import torch.nn as nn -from domainlab.compos.vae.compos.encoder_domain_topic_img2topic import \ - EncoderImg2TopicDistri -from domainlab.compos.vae.compos.encoder_domain_topic_img_topic2zd import \ - EncoderSandwichTopicImg2Zd +from domainlab.compos.vae.compos.encoder_domain_topic_img2topic import ( + EncoderImg2TopicDistri, +) +from domainlab.compos.vae.compos.encoder_domain_topic_img_topic2zd import ( + EncoderSandwichTopicImg2Zd, +) class EncoderImg2TopicDirZd(nn.Module): - """ - """ - def __init__(self, i_c, i_h, i_w, num_topics, - device, - zd_dim, - topic_h_dim, - img_h_dim, - args): + """ """ + + def __init__(self, i_c, i_h, i_w, num_topics, device, zd_dim, args): """__init__. :param i_c: @@ -23,31 +20,31 @@ def __init__(self, i_c, i_h, i_w, num_topics, :param num_topics: :param device: :param zd_dim: - :param topic_h_dim: - :param img_h_dim: (img->h_img, topic->h_topic)-> q_zd - the dimension to concatenate with topic vector to infer z_d + :param img_h_dim: + - (img->h_img, topic->h_topic)-> q_zd, + the dimension to concatenate with topic vector to infer z_d + - img->img_h_dim->topic distribution """ super().__init__() self.device = device self.zd_dim = zd_dim - self.img_h_dim = img_h_dim - self.topic_h_dim = topic_h_dim - self.add_module("net_img2topicdistri", - EncoderImg2TopicDistri( - i_c, i_h, i_w, num_topics, - self.img_h_dim, - device, - args)) + self.add_module( + "net_img2topicdistri", + EncoderImg2TopicDistri((i_c, i_h, i_w), num_topics, device, args), + ) # [topic, image] -> [h(topic), h(image)] -> [zd_mean, zd_scale] self.add_module( - "imgtopic2zd", EncoderSandwichTopicImg2Zd( - self.zd_dim, i_c, i_h, i_w, + "imgtopic2zd", + EncoderSandwichTopicImg2Zd( + self.zd_dim, + (i_c, i_h, i_w), num_topics, - topic_h_dim=self.topic_h_dim, - img_h_dim=self.img_h_dim, - args=args)) + img_h_dim=num_topics, + args=args, + ), + ) def forward(self, img): """forward. diff --git a/domainlab/compos/vae/compos/encoder_domain_topic_img2topic.py b/domainlab/compos/vae/compos/encoder_domain_topic_img2topic.py index c8b75acc1..f6d1aaa85 100644 --- a/domainlab/compos/vae/compos/encoder_domain_topic_img2topic.py +++ b/domainlab/compos/vae/compos/encoder_domain_topic_img2topic.py @@ -9,49 +9,41 @@ class EncoderImg2TopicDistri(nn.Module): image to topic distribution (not image to topic hidden representation used by another path) """ - def __init__(self, i_c, i_h, i_w, num_topics, - img_h_dim, - device, - args): + + def __init__(self, isize, num_topics, device, args): """__init__. - :param i_c: - :param i_h: - :param i_w: + :param isize: :param num_topics: :param device: """ super().__init__() self.device = device - self.img_h_dim = img_h_dim - # image->h_image->[alpha,topic] + # image->h_topic->(batchnorm, exp)[alpha,topic] - # @FIXME: net_builder = FeatExtractNNBuilderChainNodeGetter( args=args, - arg_name_of_net="nname_topic_distrib_img2topic", - arg_path_of_net="npath_topic_distrib_img2topic")() # @FIXME - - self.add_module("layer_img2hidden", - net_builder.init_business( - flag_pretrain=True, - remove_last_layer=False, - dim_out=self.img_h_dim, - i_c=i_c, i_h=i_h, i_w=i_w, args=args)) - - # self.add_module("layer_img2hidden", - # NetConvDense(i_c, i_h, i_w, - # conv_stride=conv_stride, - # args=args, - # dim_out_h=self.img_h_dim)) + arg_name_of_net="nname_encoder_x2topic_h", + arg_path_of_net="npath_encoder_x2topic_h", + )() + + self.add_module( + "layer_img2hidden", + net_builder.init_business( + flag_pretrain=True, + isize=isize, + remove_last_layer=False, + dim_out=num_topics, + args=args, + ), + ) # h_image->[alpha,topic] - self.add_module("layer_hidden2dirichlet", - EncoderH2Dirichlet( - dim_h=self.img_h_dim, - dim_topic=num_topics, - device=self.device)) + self.add_module( + "layer_hidden2dirichlet", + EncoderH2Dirichlet(dim_topic=num_topics, device=self.device), + ) def forward(self, x): """forward. diff --git a/domainlab/compos/vae/compos/encoder_domain_topic_img_topic2zd.py b/domainlab/compos/vae/compos/encoder_domain_topic_img_topic2zd.py index 84f05b432..c712c4ce0 100644 --- a/domainlab/compos/vae/compos/encoder_domain_topic_img_topic2zd.py +++ b/domainlab/compos/vae/compos/encoder_domain_topic_img_topic2zd.py @@ -1,7 +1,7 @@ import torch import torch.nn as nn -from domainlab.compos.vae.compos.encoder import LSEncoderDense +from domainlab.compos.vae.compos.encoder import LSEncoderLinear from domainlab.compos.zoo_nn import FeatExtractNNBuilderChainNodeGetter @@ -9,42 +9,40 @@ class EncoderSandwichTopicImg2Zd(nn.Module): """ sandwich encoder: (img, s)->zd """ - def __init__(self, zd_dim, i_c, i_h, i_w, num_topics, - topic_h_dim, img_h_dim, args): + + def __init__(self, zd_dim, isize, num_topics, img_h_dim, args): """ - topic_h_dim, img_h_dim: (img->h_img, topic->h_topic)-> q_zd + num_topics, img_h_dim: (img->h_img, topic->h_topic)-> q_zd :param img_h_dim: (img->h_img, topic->h_topic)-> q_zd the dimension to concatenate with topic vector to infer z_d """ super().__init__() self.zd_dim = zd_dim - self.topic_h_dim = num_topics self.img_h_dim = img_h_dim net_builder = FeatExtractNNBuilderChainNodeGetter( args=args, - arg_name_of_net="nname_encoder_sandwich_layer_img2h4zd", - arg_path_of_net="npath_encoder_sandwich_layer_img2h4zd")() # @FIXME + arg_name_of_net="nname_encoder_sandwich_x2h4zd", + arg_path_of_net="npath_encoder_sandwich_x2h4zd", + )() # image->h_img - self.add_module("layer_img2h4zd", net_builder.init_business( - dim_out=self.img_h_dim, - flag_pretrain=True, - remove_last_layer=False, - i_c=i_c, i_h=i_h, i_w=i_w, args=args)) - - # topic->h_topic - # @FIXME: do we need topic to h_topic instead of simplying using topic? - # REMOVED: self.add_module("h_layer_topic", - # REMOVED: DenseNet( - # REMOVED: input_flat_size=num_topics, - # REMOVED: out_hidden_size=self.topic_h_dim)) + self.add_module( + "layer_img2h4zd", + net_builder.init_business( + dim_out=self.img_h_dim, + flag_pretrain=True, + remove_last_layer=False, + isize=isize, + args=args, + ), + ) # [h_img, h_topic] -> zd - self.add_module("encoder_cat_topic_img_h2zd", - LSEncoderDense( - dim_input=self.img_h_dim+self.topic_h_dim, - z_dim=self.zd_dim)) + self.add_module( + "encoder_cat_topic_img_h2zd", + LSEncoderLinear(dim_input=self.img_h_dim + num_topics, z_dim=self.zd_dim), + ) def forward(self, img, vec_topic): """forward. @@ -54,10 +52,7 @@ def forward(self, img, vec_topic): """ # image->h_img h_img = self.layer_img2h4zd(img) - # topic->h_topic - # REMOVE: h_topic = self.h_layer_topic(topic) h_topic = vec_topic - # @FIXME: order of concatnation h_img_topic = torch.cat((h_img, h_topic), 1) q_zd, zd_q = self.encoder_cat_topic_img_h2zd(h_img_topic) return q_zd, zd_q diff --git a/domainlab/compos/vae/compos/encoder_xyd_parallel.py b/domainlab/compos/vae/compos/encoder_xyd_parallel.py index 91afb4cc5..2a89f9a95 100644 --- a/domainlab/compos/vae/compos/encoder_xyd_parallel.py +++ b/domainlab/compos/vae/compos/encoder_xyd_parallel.py @@ -1,8 +1,7 @@ import torch.nn as nn from domainlab.compos.vae.compos.encoder import LSEncoderConvBnReluPool -from domainlab.compos.vae.compos.encoder_zy import \ - EncoderConnectLastFeatLayer2Z +from domainlab.compos.vae.compos.encoder_zy import EncoderConnectLastFeatLayer2Z from domainlab.utils.utils_class import store_args @@ -11,6 +10,7 @@ class XYDEncoderParallel(nn.Module): calculate zx, zy, zd vars independently (without order, parallel): x->zx, x->zy, x->zd """ + def __init__(self, net_infer_zd, net_infer_zx, net_infer_zy): super().__init__() self.add_module("net_infer_zd", net_infer_zd) @@ -37,10 +37,21 @@ def infer_zy_loc(self, tensor): return zy_loc +class XYDEncoderParallelUser(XYDEncoderParallel): + """ + This class only reimplemented constructor of parent class + """ + + @store_args + def __init__(self, net_class_d, net_x, net_class_y): + super().__init__(net_class_d, net_x, net_class_y) + + class XYDEncoderParallelConvBnReluPool(XYDEncoderParallel): """ This class only reimplemented constructor of parent class """ + @store_args def __init__(self, zd_dim, zx_dim, zy_dim, i_c, i_h, i_w, conv_stride=1): """ @@ -56,16 +67,16 @@ def __init__(self, zd_dim, zx_dim, zy_dim, i_c, i_h, i_w, conv_stride=1): # Calculated output size: (64x0x0). # Output size is too small net_infer_zd = LSEncoderConvBnReluPool( - self.zd_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) + self.zd_dim, self.i_c, self.i_w, self.i_h, conv_stride=conv_stride + ) # if self.zx_dim != 0: # pytorch can generate emtpy tensor, so no need to judge here net_infer_zx = LSEncoderConvBnReluPool( - self.zx_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) + self.zx_dim, self.i_c, self.i_w, self.i_h, conv_stride=conv_stride + ) net_infer_zy = LSEncoderConvBnReluPool( - self.zy_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) + self.zy_dim, self.i_c, self.i_w, self.i_h, conv_stride=conv_stride + ) super().__init__(net_infer_zd, net_infer_zx, net_infer_zy) @@ -75,9 +86,9 @@ class XYDEncoderParallelAlex(XYDEncoderParallel): at the end of the constructor of this class, the parent class contructor is called """ + @store_args - def __init__(self, zd_dim, zx_dim, zy_dim, i_c, i_h, i_w, args, - conv_stride=1): + def __init__(self, zd_dim, zx_dim, zy_dim, i_c, i_h, i_w, args, conv_stride=1): """ :param zd_dim: :param zx_dim: @@ -91,17 +102,23 @@ def __init__(self, zd_dim, zx_dim, zy_dim, i_c, i_h, i_w, args, # Calculated output size: (64x0x0). # Output size is too small net_infer_zd = LSEncoderConvBnReluPool( - self.zd_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) + self.zd_dim, self.i_c, self.i_w, self.i_h, conv_stride=conv_stride + ) # if self.zx_dim != 0: pytorch can generate emtpy tensor, # so no need to judge here net_infer_zx = LSEncoderConvBnReluPool( - self.zx_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) - net_infer_zy = EncoderConnectLastFeatLayer2Z(self.zy_dim, True, - i_c, i_h, i_w, args, - arg_name="nname", - arg_path_name="npath") + self.zx_dim, self.i_c, self.i_w, self.i_h, conv_stride=conv_stride + ) + net_infer_zy = EncoderConnectLastFeatLayer2Z( + self.zy_dim, + True, + i_c, + i_h, + i_w, + args, + arg_name="nname", + arg_path_name="npath", + ) super().__init__(net_infer_zd, net_infer_zx, net_infer_zy) @@ -111,26 +128,38 @@ class XYDEncoderParallelExtern(XYDEncoderParallel): at the end of the constructor of this class, the parent class contructor is called """ + @store_args - def __init__(self, zd_dim, zx_dim, zy_dim, args, - i_c, i_h, i_w, conv_stride=1): + def __init__(self, zd_dim, zx_dim, zy_dim, args, i_c, i_h, i_w, conv_stride=1): """ :param zd_dim: :param zx_dim: :param zy_dim: """ - net_infer_zd = EncoderConnectLastFeatLayer2Z(self.zd_dim, True, - i_c, i_h, i_w, args, - arg_name="nname_dom", - arg_path_name="npath_dom") + net_infer_zd = EncoderConnectLastFeatLayer2Z( + self.zd_dim, + True, + i_c, + i_h, + i_w, + args, + arg_name="nname_dom", + arg_path_name="npath_dom", + ) # if self.zx_dim != 0: pytorch can generate emtpy tensor, # so no need to judge zx_dim=0 here net_infer_zx = LSEncoderConvBnReluPool( - self.zx_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) + self.zx_dim, self.i_c, self.i_w, self.i_h, conv_stride=conv_stride + ) - net_infer_zy = EncoderConnectLastFeatLayer2Z(self.zy_dim, True, - i_c, i_h, i_w, args, - arg_name="nname", - arg_path_name="npath") + net_infer_zy = EncoderConnectLastFeatLayer2Z( + self.zy_dim, + True, + i_c, + i_h, + i_w, + args, + arg_name="nname", + arg_path_name="npath", + ) super().__init__(net_infer_zd, net_infer_zx, net_infer_zy) diff --git a/domainlab/compos/vae/compos/encoder_xydt_elevator.py b/domainlab/compos/vae/compos/encoder_xydt_elevator.py index f4c5e3546..194964816 100644 --- a/domainlab/compos/vae/compos/encoder_xydt_elevator.py +++ b/domainlab/compos/vae/compos/encoder_xydt_elevator.py @@ -1,10 +1,8 @@ import torch.nn as nn from domainlab.compos.vae.compos.encoder import LSEncoderConvBnReluPool -from domainlab.compos.vae.compos.encoder_domain_topic import \ - EncoderImg2TopicDirZd -from domainlab.compos.vae.compos.encoder_zy import \ - EncoderConnectLastFeatLayer2Z +from domainlab.compos.vae.compos.encoder_domain_topic import EncoderImg2TopicDirZd +from domainlab.compos.vae.compos.encoder_zy import EncoderConnectLastFeatLayer2Z from domainlab.utils.utils_class import store_args @@ -12,6 +10,7 @@ class XYDTEncoderElevator(nn.Module): """ x->zx, x->zy, x->s, (x,s)->zd """ + def __init__(self, net_infer_zd_topic, net_infer_zx, net_infer_zy): super().__init__() self.add_module("net_infer_zd_topic", net_infer_zd_topic) @@ -42,12 +41,9 @@ class XYDTEncoderArg(XYDTEncoderElevator): """ This class only reimplemented constructor of parent class """ + @store_args - def __init__(self, device, topic_dim, zd_dim, - zx_dim, zy_dim, i_c, i_h, i_w, - args, - topic_h_dim, - img_h_dim): + def __init__(self, device, topic_dim, zd_dim, zx_dim, zy_dim, i_c, i_h, i_w, args): """ :param zd_dim: :param zx_dim: @@ -55,7 +51,8 @@ def __init__(self, device, topic_dim, zd_dim, :param i_c: number of image channels :param i_h: image height :param i_w: image width - :param img_h_dim: (img->h_img, topic->h_topic)-> q_zd + + (img->h_img=topic_dim, topic->h_topic)-> q_zd the dimension to concatenate with topic vector to infer z_d """ # conv_stride=2 on size 28 got RuntimeError: @@ -65,65 +62,28 @@ def __init__(self, device, topic_dim, zd_dim, # if self.zx_dim != 0: pytorch can generate emtpy tensor, # so no need to judge here net_infer_zx = LSEncoderConvBnReluPool( - self.zx_dim, self.i_c, self.i_w, self.i_h, - conv_stride=1) + self.zx_dim, self.i_c, self.i_w, self.i_h, conv_stride=1 + ) net_infer_zy = EncoderConnectLastFeatLayer2Z( - self.zy_dim, True, i_c, i_h, i_w, args, - arg_name="nname", arg_path_name="npath") + self.zy_dim, + True, + i_c, + i_h, + i_w, + args, + arg_name="nname", + arg_path_name="npath", + ) - net_infer_zd_topic = EncoderImg2TopicDirZd(args=args, - num_topics=topic_dim, - zd_dim=self.zd_dim, - i_c=self.i_c, - i_w=self.i_w, - i_h=self.i_h, - device=device, - topic_h_dim=topic_h_dim, - img_h_dim=img_h_dim) + net_infer_zd_topic = EncoderImg2TopicDirZd( + args=args, + num_topics=topic_dim, + zd_dim=self.zd_dim, + i_c=self.i_c, + i_w=self.i_w, + i_h=self.i_h, + device=device, + ) super().__init__(net_infer_zd_topic, net_infer_zx, net_infer_zy) - - -# To remove -class XYDTEncoderConvBnReluPool(XYDTEncoderElevator): - """ - This class only reimplemented constructor of parent class - """ - @store_args - def __init__(self, device, topic_dim, zd_dim, zx_dim, zy_dim, - i_c, i_h, i_w, - topic_h_dim, - img_h_dim, - conv_stride, - args): - """ - :param zd_dim: - :param zx_dim: - :param zy_dim: - :param i_c: number of image channels - :param i_h: image height - :param i_w: image width - """ - # conv_stride=2 on size 28 got RuntimeError: - # Given input size: (64x1x1). - # Calculated output size: (64x0x0). - # Output size is too small - net_infer_zd_topic = EncoderImg2TopicDirZd(args=args, - num_topics=topic_dim, - zd_dim=self.zd_dim, - i_c=self.i_c, - i_w=self.i_w, - i_h=self.i_h, - device=device, - topic_h_dim=topic_h_dim, - img_h_dim=img_h_dim) - # if self.zx_dim != 0: pytorch can generate emtpy tensor, - # so no need to judge here - net_infer_zx = LSEncoderConvBnReluPool( - self.zx_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) - net_infer_zy = LSEncoderConvBnReluPool( - self.zy_dim, self.i_c, self.i_w, self.i_h, - conv_stride=conv_stride) - super().__init__(net_infer_zd_topic, net_infer_zx, net_infer_zy) diff --git a/domainlab/compos/vae/compos/encoder_zy.py b/domainlab/compos/vae/compos/encoder_zy.py index c42c66527..c406d0829 100644 --- a/domainlab/compos/vae/compos/encoder_zy.py +++ b/domainlab/compos/vae/compos/encoder_zy.py @@ -12,28 +12,32 @@ class EncoderConnectLastFeatLayer2Z(nn.Module): neural network to the latent representation This class should be transparent to where to fetch the network """ - def __init__(self, z_dim, flag_pretrain, - i_c, i_h, i_w, args, arg_name, - arg_path_name): + + def __init__( + self, z_dim, flag_pretrain, i_c, i_h, i_w, args, arg_name, arg_path_name + ): """__init__. :param hidden_size: """ super().__init__() net_builder = FeatExtractNNBuilderChainNodeGetter( - args, arg_name, arg_path_name)() # request + args, arg_name, arg_path_name + )() # request self.net_feat_extract = net_builder.init_business( - flag_pretrain=flag_pretrain, dim_out=z_dim, # @FIXME - remove_last_layer=True, args=args, i_c=i_c, i_h=i_h, i_w=i_w) + flag_pretrain=flag_pretrain, + dim_out=z_dim, + remove_last_layer=True, + args=args, + isize=(i_c, i_h, i_w), + ) - size_last_layer_before_z = get_flat_dim( - self.net_feat_extract, i_c, i_h, i_w) + size_last_layer_before_z = get_flat_dim(self.net_feat_extract, i_c, i_h, i_w) - self.net_fc_mean = nn.Sequential( - nn.Linear(size_last_layer_before_z, z_dim)) + self.net_fc_mean = nn.Sequential(nn.Linear(size_last_layer_before_z, z_dim)) self.net_fc_scale = nn.Sequential( - nn.Linear(size_last_layer_before_z, z_dim), - nn.Softplus()) # for scale calculation + nn.Linear(size_last_layer_before_z, z_dim), nn.Softplus() + ) # for scale calculation torch.nn.init.xavier_uniform_(self.net_fc_mean[0].weight) self.net_fc_mean[0].bias.data.zero_() diff --git a/domainlab/compos/vae/utils_request_chain_builder.py b/domainlab/compos/vae/utils_request_chain_builder.py index b02406cb4..153399ad1 100644 --- a/domainlab/compos/vae/utils_request_chain_builder.py +++ b/domainlab/compos/vae/utils_request_chain_builder.py @@ -1,7 +1,10 @@ from domainlab.compos.vae.zoo_vae_builders_classif import ( - NodeVAEBuilderArg, NodeVAEBuilderImgAlex, NodeVAEBuilderImgConvBnPool) -from domainlab.compos.vae.zoo_vae_builders_classif_topic import \ - NodeVAEBuilderImgTopic + NodeVAEBuilderArg, + NodeVAEBuilderImgAlex, + NodeVAEBuilderImgConvBnPool, + NodeVAEBuilderUser, +) +from domainlab.compos.vae.zoo_vae_builders_classif_topic import NodeVAEBuilderImgTopic class VAEChainNodeGetter(object): @@ -11,9 +14,9 @@ class VAEChainNodeGetter(object): 3. heavy weight business objective is returned by selected node 4. convert Scenario object to request object, so that class can be reused """ + def __init__(self, request, topic_dim=None): - """ - """ + """ """ self.request = request self.topic_dim = topic_dim @@ -29,5 +32,6 @@ def __call__(self): chain = NodeVAEBuilderImgConvBnPool(None) chain = NodeVAEBuilderImgAlex(chain) chain = NodeVAEBuilderArg(chain) + chain = NodeVAEBuilderUser(chain) node = chain.handle(self.request) return node diff --git a/domainlab/compos/vae/zoo_vae_builders_classif.py b/domainlab/compos/vae/zoo_vae_builders_classif.py index db3298dc2..ef765529d 100644 --- a/domainlab/compos/vae/zoo_vae_builders_classif.py +++ b/domainlab/compos/vae/zoo_vae_builders_classif.py @@ -1,20 +1,25 @@ """ Chain node VAE builders """ -from domainlab.compos.vae.c_vae_builder_classif import \ - ChainNodeVAEBuilderClassifCondPrior -from domainlab.compos.vae.compos.decoder_concat_vec_reshape_conv_gated_conv import \ - DecoderConcatLatentFCReshapeConvGatedConv +from domainlab.compos.vae.c_vae_builder_classif import ( + ChainNodeVAEBuilderClassifCondPrior, +) +from domainlab.compos.vae.compos.decoder_concat_vec_reshape_conv_gated_conv import ( + DecoderConcatLatentFCReshapeConvGatedConv, +) from domainlab.compos.vae.compos.encoder_xyd_parallel import ( - XYDEncoderParallelAlex, XYDEncoderParallelConvBnReluPool, - XYDEncoderParallelExtern) + XYDEncoderParallelAlex, + XYDEncoderParallelConvBnReluPool, + XYDEncoderParallelExtern, + XYDEncoderParallelUser, +) -class ChainNodeVAEBuilderClassifCondPriorBase( - ChainNodeVAEBuilderClassifCondPrior): +class ChainNodeVAEBuilderClassifCondPriorBase(ChainNodeVAEBuilderClassifCondPrior): """ base class of AE builder """ + def config_img(self, flag, request): """config_img. @@ -40,15 +45,17 @@ def build_encoder(self): def build_decoder(self): """build_decoder.""" decoder = DecoderConcatLatentFCReshapeConvGatedConv( - z_dim=self.zd_dim+self.zx_dim+self.zy_dim, - i_c=self.i_c, i_w=self.i_w, - i_h=self.i_h) + z_dim=self.zd_dim + self.zx_dim + self.zy_dim, + i_c=self.i_c, + i_w=self.i_w, + i_h=self.i_h, + ) return decoder class NodeVAEBuilderArg(ChainNodeVAEBuilderClassifCondPriorBase): - """Build encoder decoder according to commandline arguments - """ + """Build encoder decoder according to commandline arguments""" + def is_myjob(self, request): """is_myjob. :param request: @@ -63,10 +70,30 @@ def is_myjob(self, request): def build_encoder(self): """build_encoder.""" encoder = XYDEncoderParallelExtern( - self.zd_dim, self.zx_dim, self.zy_dim, args=self.args, + self.zd_dim, + self.zx_dim, + self.zy_dim, + args=self.args, i_c=self.i_c, i_h=self.i_h, - i_w=self.i_w) + i_w=self.i_w, + ) + return encoder + + +class NodeVAEBuilderUser(ChainNodeVAEBuilderClassifCondPriorBase): + """Build encoders according to test_mk_exp file""" + + def is_myjob(self, request): + flag = not hasattr(request, "args") + self.request = request + self.config_img(flag, request) + return flag + + def build_encoder(self): + encoder = XYDEncoderParallelUser( + self.request.net_class_d, self.request.net_x, self.request.net_class_y + ) return encoder @@ -76,18 +103,18 @@ def is_myjob(self, request): :param request: """ - flag = (request.args.nname == "conv_bn_pool_2" or - request.args.nname_dom == "conv_bn_pool_2") # @FIXME + flag = ( + request.args.nname == "conv_bn_pool_2" + or request.args.nname_dom == "conv_bn_pool_2" + ) # @FIXME self.config_img(flag, request) return flag def build_encoder(self): """build_encoder.""" encoder = XYDEncoderParallelConvBnReluPool( - self.zd_dim, self.zx_dim, self.zy_dim, - self.i_c, - self.i_h, - self.i_w) + self.zd_dim, self.zx_dim, self.zy_dim, self.i_c, self.i_h, self.i_w + ) return encoder @@ -100,15 +127,19 @@ def is_myjob(self, request): :param request: """ self.args = request.args - flag = (self.args.nname == "alexnet") # @FIXME + flag = self.args.nname == "alexnet" # @FIXME self.config_img(flag, request) return flag def build_encoder(self): """build_encoder.""" encoder = XYDEncoderParallelAlex( - self.zd_dim, self.zx_dim, self.zy_dim, + self.zd_dim, + self.zx_dim, + self.zy_dim, self.i_c, self.i_h, - self.i_w, args=self.args) + self.i_w, + args=self.args, + ) return encoder diff --git a/domainlab/compos/vae/zoo_vae_builders_classif_topic.py b/domainlab/compos/vae/zoo_vae_builders_classif_topic.py index b8164224e..2508b40bd 100644 --- a/domainlab/compos/vae/zoo_vae_builders_classif_topic.py +++ b/domainlab/compos/vae/zoo_vae_builders_classif_topic.py @@ -1,14 +1,16 @@ """ Chain node VAE builders """ -from domainlab.compos.vae.compos.decoder_concat_vec_reshape_conv_gated_conv import \ - DecoderConcatLatentFCReshapeConvGatedConv +from domainlab.compos.vae.compos.decoder_concat_vec_reshape_conv_gated_conv import ( + DecoderConcatLatentFCReshapeConvGatedConv, +) from domainlab.compos.vae.compos.encoder_xydt_elevator import XYDTEncoderArg from domainlab.compos.vae.zoo_vae_builders_classif import NodeVAEBuilderArg class NodeVAEBuilderImgTopic(NodeVAEBuilderArg): """NodeVAEBuilderImgTopic.""" + def is_myjob(self, request): """is_myjob. @@ -25,15 +27,17 @@ def build_encoder(self, device, topic_dim): :param device: :param topic_dim: """ - encoder = XYDTEncoderArg(device, topic_dim, - self.zd_dim, self.zx_dim, - self.zy_dim, - self.i_c, - self.i_h, - self.i_w, - topic_h_dim=self.args.topic_h_dim, - img_h_dim=self.args.img_h_dim, - args=self.args) + encoder = XYDTEncoderArg( + device, + topic_dim, + self.zd_dim, + self.zx_dim, + self.zy_dim, + self.i_c, + self.i_h, + self.i_w, + args=self.args, + ) return encoder def build_decoder(self, topic_dim): @@ -42,7 +46,9 @@ def build_decoder(self, topic_dim): :param topic_dim: """ decoder = DecoderConcatLatentFCReshapeConvGatedConv( - z_dim=self.zd_dim+self.zx_dim+self.zy_dim+topic_dim, - i_c=self.i_c, i_w=self.i_w, - i_h=self.i_h) + z_dim=self.zd_dim + self.zx_dim + self.zy_dim + topic_dim, + i_c=self.i_c, + i_w=self.i_w, + i_h=self.i_h, + ) return decoder diff --git a/domainlab/compos/zoo_nn.py b/domainlab/compos/zoo_nn.py index 1cc2f2e6e..ba3dfed3c 100644 --- a/domainlab/compos/zoo_nn.py +++ b/domainlab/compos/zoo_nn.py @@ -1,10 +1,10 @@ -import copy - from domainlab.compos.builder_nn_alex import mkNodeFeatExtractNNBuilderNameAlex -from domainlab.compos.builder_nn_conv_bn_relu_2 import \ - mkNodeFeatExtractNNBuilderNameConvBnRelu2 -from domainlab.compos.builder_nn_external_from_file import \ - mkNodeFeatExtractNNBuilderExternFromFile +from domainlab.compos.builder_nn_conv_bn_relu_2 import ( + mkNodeFeatExtractNNBuilderNameConvBnRelu2, +) +from domainlab.compos.builder_nn_external_from_file import ( + mkNodeFeatExtractNNBuilderExternFromFile, +) class FeatExtractNNBuilderChainNodeGetter(object): @@ -12,8 +12,8 @@ class FeatExtractNNBuilderChainNodeGetter(object): 1. Hardcoded chain 3. Return selected node """ - def __init__(self, args, arg_name_of_net, - arg_path_of_net): + + def __init__(self, args, arg_name_of_net, arg_path_of_net): """__init__. :param args: command line arguments :param arg_name_of_net: args.npath to specify @@ -30,14 +30,14 @@ def __call__(self): 2. hard code seems to be the best solution """ chain = mkNodeFeatExtractNNBuilderNameConvBnRelu2( - self.arg_name_of_net, - arg_val="conv_bn_pool_2", conv_stride=1)(None) + self.arg_name_of_net, arg_val="conv_bn_pool_2", conv_stride=1 + )(None) chain = mkNodeFeatExtractNNBuilderNameConvBnRelu2( - arg_name4net="nname_dom", - arg_val="conv_bn_pool_2", conv_stride=1)(chain) - chain = mkNodeFeatExtractNNBuilderNameAlex( - self.arg_name_of_net, "alexnet")(chain) - chain = mkNodeFeatExtractNNBuilderExternFromFile( - self.arg_path_of_net)(chain) + arg_name4net="nname_dom", arg_val="conv_bn_pool_2", conv_stride=1 + )(chain) + chain = mkNodeFeatExtractNNBuilderNameAlex(self.arg_name_of_net, "alexnet")( + chain + ) + chain = mkNodeFeatExtractNNBuilderExternFromFile(self.arg_path_of_net)(chain) node = chain.handle(self.request) return node diff --git a/domainlab/dsets/a_dset_mnist_color_rgb_solo.py b/domainlab/dsets/a_dset_mnist_color_rgb_solo.py index cf1bd805c..07b88df31 100644 --- a/domainlab/dsets/a_dset_mnist_color_rgb_solo.py +++ b/domainlab/dsets/a_dset_mnist_color_rgb_solo.py @@ -22,6 +22,7 @@ class ADsetMNISTColorRGBSolo(Dataset, metaclass=abc.ABCMeta): 3. structure: each subdomain contains a combination of foreground+background color """ + @abc.abstractmethod def get_foreground_color(self, ind): raise NotImplementedError @@ -35,14 +36,17 @@ def get_num_colors(self): raise NotImplementedError @store_args - def __init__(self, ind_color, path, - subset_step=100, - color_scheme="both", - label_transform=mk_fun_label2onehot(10), - list_transforms=None, - raw_split='train', - flag_rand_color=False, - ): + def __init__( + self, + ind_color, + path="zoutput", + subset_step=100, + color_scheme="both", + label_transform=mk_fun_label2onehot(10), + list_transforms=None, + raw_split="train", + flag_rand_color=False, + ): """ :param ind_color: index of a color palette :param path: disk storage directory @@ -58,14 +62,13 @@ def __init__(self, ind_color, path, """ dpath = os.path.normpath(path) flag_train = True - if raw_split!="train": + if raw_split != "train": flag_train = False - dataset = datasets.MNIST(root=dpath, - train=flag_train, - download=True, - transform=transforms.ToTensor()) + dataset = datasets.MNIST( + root=dpath, train=flag_train, download=True, transform=transforms.ToTensor() + ) - if color_scheme not in ['num', 'back', 'both']: + if color_scheme not in ["num", "back", "both"]: raise ValueError("color must be either 'num', 'back' or 'both") raw_path = os.path.dirname(dataset.raw_folder) self._collect_imgs_labels(raw_path, raw_split) @@ -79,21 +82,20 @@ def _collect_imgs_labels(self, path, raw_split): :param path: :param raw_split: """ - if raw_split == 'train': - fimages = os.path.join(path, 'raw', 'train-images-idx3-ubyte') - flabels = os.path.join(path, 'raw', 'train-labels-idx1-ubyte') + if raw_split == "train": + fimages = os.path.join(path, "raw", "train-images-idx3-ubyte") + flabels = os.path.join(path, "raw", "train-labels-idx1-ubyte") else: - fimages = os.path.join(path, 'raw', 't10k-images-idx3-ubyte') - flabels = os.path.join(path, 'raw', 't10k-labels-idx1-ubyte') + fimages = os.path.join(path, "raw", "t10k-images-idx3-ubyte") + flabels = os.path.join(path, "raw", "t10k-labels-idx1-ubyte") # Load images - with open(fimages, 'rb') as f_h: + with open(fimages, "rb") as f_h: _, _, rows, cols = struct.unpack(">IIII", f_h.read(16)) - self.images = np.fromfile(f_h, dtype=np.uint8).reshape( - -1, rows, cols) + self.images = np.fromfile(f_h, dtype=np.uint8).reshape(-1, rows, cols) # Load labels - with open(flabels, 'rb') as f_h: + with open(flabels, "rb") as f_h: struct.unpack(">II", f_h.read(8)) self.labels = np.fromfile(f_h, dtype=np.int8) self.images = np.tile(self.images[:, :, :, np.newaxis], 3) @@ -107,37 +109,41 @@ def _op_color_img(self, image): """ # randomcolor is a flag orthogonal to num-back-both if self.flag_rand_color: - c_f = self.get_foreground_color(np.random.randint(0, self.get_num_colors())) c_b = 0 - if self.color_scheme == 'both': + if self.color_scheme == "both": count = 0 while True: - c_b = self.get_background_color(np.random.randint(0, self.get_num_colors())) + c_b = self.get_background_color( + np.random.randint(0, self.get_num_colors()) + ) if c_b != c_f and count < 10: # exit loop if background color # is not equal to foreground break else: - if self.color_scheme == 'num': + if self.color_scheme == "num": # domain and class label has perfect mutual information: # assign color # according to their class (0,10) c_f = self.get_foreground_color(self.ind_color) - c_b = np.array([0]*3) - elif self.color_scheme == 'back': # only paint background - c_f = np.array([0]*3) + c_b = np.array([0] * 3) + elif self.color_scheme == "back": # only paint background + c_f = np.array([0] * 3) c_b = self.get_background_color(self.ind_color) else: # paint both background and foreground c_f = self.get_foreground_color(self.ind_color) c_b = self.get_background_color(self.ind_color) - image[:, :, 0] = image[:, :, 0] / 255 * c_f[0] + \ - (255 - image[:, :, 0]) / 255 * c_b[0] - image[:, :, 1] = image[:, :, 1] / 255 * c_f[1] + \ - (255 - image[:, :, 1]) / 255 * c_b[1] - image[:, :, 2] = image[:, :, 2] / 255 * c_f[2] + \ - (255 - image[:, :, 2]) / 255 * c_b[2] + image[:, :, 0] = ( + image[:, :, 0] / 255 * c_f[0] + (255 - image[:, :, 0]) / 255 * c_b[0] + ) + image[:, :, 1] = ( + image[:, :, 1] / 255 * c_f[1] + (255 - image[:, :, 1]) / 255 * c_b[1] + ) + image[:, :, 2] = ( + image[:, :, 2] / 255 * c_f[2] + (255 - image[:, :, 2]) / 255 * c_b[2] + ) return image def _color_imgs_onehot_labels(self): @@ -153,7 +159,7 @@ def __getitem__(self, idx): label = self.labels[idx] if self.label_transform is not None: label = self.label_transform(label) - image = Image.fromarray(image) # numpy array 28*28*3 -> 3*28*28 + image = Image.fromarray(image) # numpy array 28*28*3 -> 3*28*28 if self.list_transforms is not None: for trans in self.list_transforms: image = trans(image) diff --git a/domainlab/dsets/dset_img_path_list.py b/domainlab/dsets/dset_img_path_list.py index e94453d25..bf36feff1 100644 --- a/domainlab/dsets/dset_img_path_list.py +++ b/domainlab/dsets/dset_img_path_list.py @@ -16,14 +16,16 @@ def __init__(self, root_img, path2filelist, trans_img=None, trans_target=None): self.get_list_tuple_img_label() def get_list_tuple_img_label(self): - with open(self.path2filelist, 'r') as f_h: + with open(self.path2filelist, "r") as f_h: for str_line in f_h.readlines(): path_img, label_img = str_line.strip().split() - self.list_tuple_img_label.append((path_img, int(label_img))) # @FIXME: string to int, not necessarily continuous + self.list_tuple_img_label.append( + (path_img, int(label_img)) + ) # @FIXME: string to int, not necessarily continuous def __getitem__(self, index): path_img, target = self.list_tuple_img_label[index] - target = target - 1 # @FIXME: make this more general + target = target - 1 # @FIXME: make this more general img = fun_img_path_loader_default(os.path.join(self.root_img, path_img)) if self.trans_img is not None: img = self.trans_img(img) diff --git a/domainlab/dsets/dset_mnist_color_solo_default.py b/domainlab/dsets/dset_mnist_color_solo_default.py index 9b14781ea..bbf2276c4 100644 --- a/domainlab/dsets/dset_mnist_color_solo_default.py +++ b/domainlab/dsets/dset_mnist_color_solo_default.py @@ -11,10 +11,10 @@ def get_num_colors(self): return len(self.palette) def get_background_color(self, ind): - if self.color_scheme == 'back': + if self.color_scheme == "back": return self.palette[ind] - if self.color_scheme == 'both': - return self.palette[-(ind-3)] + if self.color_scheme == "both": + return self.palette[-(ind - 3)] # only array can be multiplied with number 255 directly return self.palette[ind] # "num" do not use background at all diff --git a/domainlab/dsets/dset_poly_domains_mnist_color_default.py b/domainlab/dsets/dset_poly_domains_mnist_color_default.py index c51cc70c3..47240055c 100644 --- a/domainlab/dsets/dset_poly_domains_mnist_color_default.py +++ b/domainlab/dsets/dset_poly_domains_mnist_color_default.py @@ -4,8 +4,7 @@ import numpy as np from torch.utils.data import Dataset -from domainlab.dsets.dset_mnist_color_solo_default import \ - DsetMNISTColorSoloDefault +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault from domainlab.dsets.utils_data import mk_fun_label2onehot @@ -13,14 +12,15 @@ class DsetMNISTColorMix(Dataset): """ merge several solo-color mnist to form a mixed dataset """ - def __init__(self, n_domains, path, color_scheme='both'): + + def __init__(self, n_domains, path, color_scheme="both"): self.n_domains = n_domains self.list_dset = [None] * n_domains self.fun_dlabel2onehot = mk_fun_label2onehot(n_domains) for domain_ind in range(n_domains): - self.list_dset[domain_ind] = \ - DsetMNISTColorSoloDefault(domain_ind, path, - color_scheme=color_scheme) + self.list_dset[domain_ind] = DsetMNISTColorSoloDefault( + domain_ind, path, color_scheme=color_scheme + ) self.list_len = [len(ds) for ds in self.list_dset] self.size_single = min(self.list_len) @@ -29,7 +29,7 @@ def __len__(self): return sum(self.list_len) def __getitem__(self, idx): - rand_domain = np.random.random_integers(self.n_domains-1) # @FIXME + rand_domain = np.random.random_integers(self.n_domains - 1) # @FIXME idx_local = idx % self.size_single img, c_label = self.list_dset[rand_domain][idx_local] return img, c_label, self.fun_dlabel2onehot(rand_domain) @@ -39,6 +39,7 @@ class DsetMNISTColorMixNoDomainLabel(DsetMNISTColorMix): """ DsetMNISTColorMixNoDomainLabel """ + def __getitem__(self, idx): img, c_label, _ = super().__getitem__(idx) return img, c_label diff --git a/domainlab/dsets/dset_subfolder.py b/domainlab/dsets/dset_subfolder.py index 792fac693..0d29f18b6 100644 --- a/domainlab/dsets/dset_subfolder.py +++ b/domainlab/dsets/dset_subfolder.py @@ -8,7 +8,9 @@ from typing import Any, Tuple from torchvision.datasets import DatasetFolder -from rich import print as rprint + +from domainlab.utils.logger import Logger + def has_file_allowed_extension(filename: str, extensions: Tuple[str, ...]) -> bool: """ @@ -38,8 +40,10 @@ def fetch_img_paths(path_dir, class_to_idx, extensions=None, is_valid_file=None) # raise ValueError( # "Both extensions and is_valid_file cannot be None or not None at the same time") if extensions is not None: + def functor_is_valid_file(filena): return has_file_allowed_extension(filena, extensions) + is_valid_file = functor_is_valid_file for target in sorted(class_to_idx.keys()): apath = os.path.join(path_dir, target) @@ -50,7 +54,7 @@ def functor_is_valid_file(filena): path_file = os.path.join(root, fname) if is_valid_file(path_file): item = (path_file, class_to_idx[target]) - list_tuple_path_cls_ind.append(item) # @FIXME + list_tuple_path_cls_ind.append(item) # @FIXME return list_tuple_path_cls_ind @@ -59,25 +63,39 @@ class DsetSubFolder(DatasetFolder): Only use user provided class names, ignore the other subfolders :param list_class_dir: list of class directories to use as classes """ - def __init__(self, root, loader, list_class_dir, extensions=None, transform=None, - target_transform=None, is_valid_file=None): + + def __init__( + self, + root, + loader, + list_class_dir, + extensions=None, + transform=None, + target_transform=None, + is_valid_file=None, + ): self.list_class_dir = list_class_dir if is_valid_file is not None and extensions is not None: raise ValueError( - "Both extensions and is_valid_file cannot be not None at the same time") + "Both extensions and is_valid_file cannot be not None at the same time" + ) if is_valid_file is None and extensions is None: # setting default extensions - extensions = ('jpg', 'jpeg', 'png') + extensions = ("jpg", "jpeg", "png") + logger = Logger.get_logger() + logger.warn("no user provided extensions, set to be jpg, jpeg, png") warnings.warn("no user provided extensions, set to be jpg, jpeg, png") - super().__init__(root, - loader, - extensions=extensions, - transform=transform, - target_transform=target_transform, - is_valid_file=is_valid_file) + super().__init__( + root, + loader, + extensions=extensions, + transform=transform, + target_transform=target_transform, + is_valid_file=is_valid_file, + ) classes, class_to_idx = self._find_classes(self.root) samples = fetch_img_paths(self.root, class_to_idx, extensions, is_valid_file) self.classes = classes @@ -114,20 +132,29 @@ def _find_classes(self, mdir): Ensures: No class is a submdirectory of another. """ + logger = Logger.get_logger() if sys.version_info >= (3, 5): # Faster and available in Python 3.5 and above list_subfolders = [subfolder.name for subfolder in list(os.scandir(mdir))] - rprint("list of subfolders", list_subfolders) - classes = [d.name for d in os.scandir(mdir) \ - if d.is_dir() and d.name in self.list_class_dir] + logger.info(f"list of subfolders {list_subfolders}") + classes = [ + d.name + for d in os.scandir(mdir) + if d.is_dir() and d.name in self.list_class_dir + ] else: - classes = [d for d in os.listdir(mdir) \ - if os.path.isdir(os.path.join(mdir, d)) and d in self.list_class_dir] - flag_user_input_classes_in_folder = (set(self.list_class_dir) <= set(classes)) + classes = [ + d + for d in os.listdir(mdir) + if os.path.isdir(os.path.join(mdir, d)) and d in self.list_class_dir + ] + flag_user_input_classes_in_folder = set(self.list_class_dir) <= set(classes) if not flag_user_input_classes_in_folder: - print("user provided class names:", self.list_class_dir) - print("subfolder names from folder:", mdir, classes) - raise RuntimeError("user provided class names does not match the subfolder names") + logger.info(f"user provided class names: {self.list_class_dir}") + logger.info(f"subfolder names from folder: {mdir} {classes}") + raise RuntimeError( + "user provided class names does not match the subfolder names" + ) classes.sort() class_to_idx = {classes[i]: i for i in range(len(classes))} return classes, class_to_idx diff --git a/domainlab/dsets/utils_color_palette.py b/domainlab/dsets/utils_color_palette.py index 6a0f6f106..5699d687c 100644 --- a/domainlab/dsets/utils_color_palette.py +++ b/domainlab/dsets/utils_color_palette.py @@ -1,12 +1,12 @@ default_rgb_palette = [ - [31, 119, 180], - [255, 127, 14], - [44, 160, 44], - [214, 39, 40], - [148, 103, 189], - [140, 86, 75], - [227, 119, 194], - [127, 127, 127], - [188, 189, 34], - [23, 190, 207] - ] + [31, 119, 180], + [255, 127, 14], + [44, 160, 44], + [214, 39, 40], + [148, 103, 189], + [140, 86, 75], + [227, 119, 194], + [127, 127, 127], + [188, 189, 34], + [23, 190, 207], +] diff --git a/domainlab/dsets/utils_data.py b/domainlab/dsets/utils_data.py index 7466c2f5d..319b3d5a2 100644 --- a/domainlab/dsets/utils_data.py +++ b/domainlab/dsets/utils_data.py @@ -9,12 +9,14 @@ from torch.utils.data import Dataset from torchvision.utils import save_image +from domainlab.utils.logger import Logger + def fun_img_path_loader_default(path): """ https://discuss.pytorch.org/t/handling-rgba-images/88428/4 """ - return Image.open(path).convert('RGB') + return Image.open(path).convert("RGB") def mk_fun_label2onehot(dim): @@ -22,12 +24,14 @@ def mk_fun_label2onehot(dim): function generator index to onehot """ + def fun_label2onehot(label): """ :param label: """ m_eye = torch.eye(dim) return m_eye[label] + return fun_label2onehot @@ -66,6 +70,7 @@ class DsetInMemDecorator(Dataset): """ fetch all items of a dataset into memory """ + def __init__(self, dset, name=None): """ :param dset: x, y, *d @@ -73,13 +78,14 @@ def __init__(self, dset, name=None): """ self.dset = dset self.item_list = [] + logger = Logger.get_logger() if name is not None: - print("loading dset ", name) + logger.info(f"loading dset {name}") t_0 = datetime.datetime.now() for i in range(len(self.dset)): self.item_list.append(self.dset[i]) t_1 = datetime.datetime.now() - print("loading dataset to memory taken: ", t_1-t_0) + logger.info(f"loading dataset to memory taken: {t_1 - t_0}") def __getitem__(self, idx): """ diff --git a/domainlab/dsets/utils_wrapdset_patches.py b/domainlab/dsets/utils_wrapdset_patches.py index 26b72d5e7..79fe6d7c1 100644 --- a/domainlab/dsets/utils_wrapdset_patches.py +++ b/domainlab/dsets/utils_wrapdset_patches.py @@ -1,36 +1,45 @@ """ -upon a task, if jigen is chosen as the algorithm, then task's dataset has to be augmented to -include tile permutation +upon a task, if Jigen is chosen as the model, then task's dataset has to be decorated with image tile permutation +note that task's dataset already include standard image +transformations like random croped resized, or flip, and normalization. See also the JiGen paper's implementation here: +https://github.com/fmcarlucci/JigenDG/blob/master/data/JigsawLoader.py """ import os + import numpy as np import torch import torchvision -from torchvision import transforms from torch.utils import data as torchdata +from torchvision import transforms class WrapDsetPatches(torchdata.Dataset): """ given dataset of images, return permuations of tiles of images re-weaved """ - def __init__(self, dataset, - num_perms2classify, - prob_no_perm, - grid_len, - ppath=None, - flag_do_not_weave_tiles=False): + + def __init__( + self, + dataset, + num_perms2classify, + prob_no_perm, + grid_len, + ppath=None, + flag_do_not_weave_tiles=False, + ): """ - :param prob_no_perm: probability of no permutation + :param prob_no_perm: probability of no permutation: permutation will change the image, so + the class label classifier will behave very differently compared to no permutation """ if ppath is None and grid_len != 3: - raise RuntimeError("please provide npy file of numpy array with each row \ + raise RuntimeError( + "please provide npy file of numpy array with each row \ being a permutation of the number of tiles, currently \ - we only support grid length 3") + we only support grid length 3" + ) self.dataset = dataset self._to_tensor = transforms.Compose([transforms.ToTensor()]) - self.arr1perm_per_row = self.__retrieve_permutations( - num_perms2classify, ppath) + self.arr1perm_per_row = self.__retrieve_permutations(num_perms2classify, ppath) # for 3*3 tiles, there are 9*8*7*6*5*...*1 >> 100, # we load from disk instead only 100 permutations # each row of the loaded array is a permutation of the 3*3 tile @@ -41,12 +50,13 @@ def __init__(self, dataset, if flag_do_not_weave_tiles: self.fun_weave_imgs = lambda x: x else: + def make_grid(img): """ sew tiles together to be an image """ - return torchvision.utils.make_grid( - img, nrow=self.grid_len, padding=0) + return torchvision.utils.make_grid(img, nrow=self.grid_len, padding=0) + self.fun_weave_imgs = make_grid def get_tile(self, img, ind_tile): @@ -67,23 +77,33 @@ def get_tile(self, img, ind_tile): img_pil = functor_tr(img) # PIL.crop((left, top, right, bottom)) # get rectangular region from box of [left, upper, right, lower] - tile = img_pil.crop([ind_horizontal * num_tiles, - ind_vertical * num_tiles, - (ind_horizontal + 1) * num_tiles, - (ind_vertical + 1) * num_tiles]) + tile = img_pil.crop( + [ + ind_horizontal * num_tiles, + ind_vertical * num_tiles, + (ind_horizontal + 1) * num_tiles, + (ind_vertical + 1) * num_tiles, + ] + ) tile = self._to_tensor(tile) return tile def __getitem__(self, index): - img, label, *_ = self.dataset.__getitem__(index) - num_grids = self.grid_len ** 2 + # image transformation from self.dataset happens here: + img, label, *domain = self.dataset.__getitem__(index) + # now img has been transformed (including normalization) + original_size = img.shape[-2:] + if domain: + dlabel = domain[0] + else: + dlabel = None + num_grids = self.grid_len**2 # divide image into grid_len^2 tiles list_tiles = [None] * num_grids # list of length num_grids of image tiles for ind_tile in range(num_grids): - list_tiles[ind_tile] = self.get_tile(img, ind_tile) # populate tile list - ind_which_perm = np.random.randint( - self.arr1perm_per_row.shape[0] + 1) + list_tiles[ind_tile] = self.get_tile(img, ind_tile) # populate tile list + ind_which_perm = np.random.randint(self.arr1perm_per_row.shape[0] + 1) # +1 in line above is for when image is not permutated, which # also need to be classified corrected by the permutation classifier # let len(self.arr1perm_per_row)=31 @@ -91,23 +111,33 @@ def __getitem__(self, index): # ind_which_perm is basically the row index to choose # from self.arr1perm_per_row which is a matrix of 31*9 # where 9=3*3 is the number of tiles the image is broken into - if self.prob_no_perm: # probability of no permutation of tiles + if self.prob_no_perm > 0: # probability of no permutation of tiles + # note that this "if" block is not redundant: permutation will change the image + # thus change the behavior of the class label classifier, if self.prob_no_perm=1.0 + # then the algorithm will behave similarly to erm, though not completely same + # FIXME: what hyperparameters one could set to let jigen=erm? if self.prob_no_perm > np.random.rand(): ind_which_perm = 0 # ind_which_perm = 0 means no permutation, the classifier need to # judge if the image has not been permutated as well list_reordered_tiles = None if ind_which_perm == 0: - list_reordered_tiles = list_tiles # no permutation - else: # default + list_reordered_tiles = list_tiles # no permutation of images + else: # default perm_chosen = self.arr1perm_per_row[ind_which_perm - 1] - list_reordered_tiles = [list_tiles[perm_chosen[ind_tile]] - for ind_tile in range(num_grids)] + list_reordered_tiles = [ + list_tiles[perm_chosen[ind_tile]] for ind_tile in range(num_grids) + ] stacked_tiles = torch.stack(list_reordered_tiles, 0) - # the 0th dim is the batch dimension - # ind_which_perm = 0 means no permutation, the classifier need to + # NOTE: stacked_tiles will be [9, 3, 30, 30], which will be weaved to + # be a whole image again by self.fun_weave_imgs + # NOTE: ind_which_perm = 0 means no permutation, the classifier need to # judge if the image has not been permutated as well - return self.fun_weave_imgs(stacked_tiles), label, int(ind_which_perm) + re_tiled_img = self.fun_weave_imgs(stacked_tiles) + img_re_tiled_re_shaped = torchvision.transforms.RandomResizedCrop( + original_size + )(re_tiled_img) + return img_re_tiled_re_shaped, label, dlabel, int(ind_which_perm) # ind_which_perm is the ground truth for the permutation index def __len__(self): @@ -122,8 +152,8 @@ def __retrieve_permutations(self, num_perms_as_classes, ppath=None): # @FIXME: this assumes always a relative path mdir = os.path.dirname(os.path.realpath(__file__)) if ppath is None: - ppath = f'data/patches_permutation4jigsaw/permutations_{num_perms_as_classes}.npy' - mpath = os.path.join(mdir, "..", "..", ppath) + ppath = f"zdata/patches_permutation4jigsaw/permutations_{num_perms_as_classes}.npy" + mpath = os.path.join(mdir, "..", ppath) arr_permutation_rows = np.load(mpath) # from range [1,9] to [0,8] since python array start with 0 if arr_permutation_rows.min() == 1: diff --git a/domainlab/exp/__init__.py b/domainlab/exp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/domainlab/compos/exp/exp_cuda_seed.py b/domainlab/exp/exp_cuda_seed.py similarity index 100% rename from domainlab/compos/exp/exp_cuda_seed.py rename to domainlab/exp/exp_cuda_seed.py diff --git a/domainlab/exp/exp_main.py b/domainlab/exp/exp_main.py new file mode 100755 index 000000000..51397131b --- /dev/null +++ b/domainlab/exp/exp_main.py @@ -0,0 +1,132 @@ +""" +experiment +""" +import datetime +import os +import warnings + +from domainlab.algos.zoo_algos import AlgoBuilderChainNodeGetter +from domainlab.exp.exp_utils import AggWriter +from domainlab.tasks.zoo_tasks import TaskChainNodeGetter +from domainlab.utils.logger import Logger +from domainlab.utils.sanity_check import SanityCheck + +os.environ["CUDA_LAUNCH_BLOCKING"] = "1" # debug + + +class Exp: + """ + Exp is combination of Task, Algorithm, and Configuration (including random seed) + """ + + def __init__(self, args, task=None, model=None, observer=None, visitor=AggWriter): + """ + :param args: + :param task: default None + :param model: default None + """ + self.task = task + self.curr_dir = os.getcwd() + if task is None: + self.task = TaskChainNodeGetter(args)() + + self.args = args + algo_builder = AlgoBuilderChainNodeGetter( + self.args.model, self.args.apath + )() # request + # the critical logic below is to avoid circular dependence between task initialization + # and trainer initialization: + + self.trainer, self.model, observer_default, device = algo_builder.init_business( + self + ) + # sanity check has to be done after init_business + # jigen algorithm builder has method dset_decoration_args_algo, which could AOP + # into the task intilization process + if args.san_check: + sancheck = SanityCheck(args, self.task) + sancheck.dataset_sanity_check() + + if model is not None: + self.model = model + self.epochs = self.args.epos + self.epoch_counter = 1 + if observer is None: + observer = observer_default + if not self.trainer.flag_initialized: + self.trainer.init_business(self.model, self.task, observer, device, args) + self.visitor = visitor(self) # visitor depends on task initialization first + # visitor must be initialized last after trainer is initialized + self.model.set_saver(self.visitor) + + def execute(self, num_epochs=None): + """ + train model + check performance by loading persisted model + """ + if num_epochs is None: + num_epochs = self.epochs + 1 + t_0 = datetime.datetime.now() + logger = Logger.get_logger() + logger.info(f"\n Experiment start at: {str(t_0)}") + t_c = t_0 + self.trainer.before_tr() + for epoch in range(1, num_epochs): + t_before_epoch = t_c + flag_stop = self.trainer.tr_epoch(epoch) + t_c = datetime.datetime.now() + logger.info( + f"after epoch: {epoch}," + f"now: {str(t_c)}," + f"epoch time: {t_c - t_before_epoch}," + f"used: {t_c - t_0}," + f"model: {self.visitor.model_name}" + ) + logger.info(f"working direcotry: {self.curr_dir}") + # current time, time since experiment start, epoch time + if flag_stop: + self.epoch_counter = epoch + logger.info("early stop trigger") + break + if epoch == self.epochs: + self.epoch_counter = self.epochs + else: + self.epoch_counter += 1 + logger.info( + f"Experiment finished at epoch: {self.epoch_counter} " + f"with time: {t_c - t_0} at {t_c}" + ) + self.trainer.post_tr() + + def clean_up(self): + """ + to be called by a decorator + """ + try: + # oracle means use out-of-domain test accuracy to select the model + self.visitor.remove("oracle") # pylint: disable=E1101 + except FileNotFoundError: + pass + + try: + # the last epoch: + # have a model to evaluate in case the training stops in between + self.visitor.remove("epoch") # pylint: disable=E1101 + except FileNotFoundError: + logger = Logger.get_logger() + logger.warn("failed to remove model_epoch: file not found") + warnings.warn("failed to remove model_epoch: file not found") + + try: + # without suffix: the selected model + self.visitor.remove() # pylint: disable=E1101 + except FileNotFoundError: + logger = Logger.get_logger() + logger.warn("failed to remove model") + warnings.warn("failed to remove model") + + try: + # for matchdg + self.visitor.remove("ctr") # pylint: disable=E1101 + except FileNotFoundError: + pass diff --git a/domainlab/compos/exp/exp_utils.py b/domainlab/exp/exp_utils.py similarity index 59% rename from domainlab/compos/exp/exp_utils.py rename to domainlab/exp/exp_utils.py index 0e6928d0e..2af681731 100644 --- a/domainlab/compos/exp/exp_utils.py +++ b/domainlab/exp/exp_utils.py @@ -1,22 +1,25 @@ """ -This module contains 3 classes inheriting: ExpProtocolAggWriter(AggWriter(ExpModelPersistVisitor)) +This module contains 3 classes inheriting: + ExpProtocolAggWriter(AggWriter(ExpModelPersistVisitor)) """ import copy import datetime import os from pathlib import Path +import numpy as np import torch +from sklearn.metrics import ConfusionMatrixDisplay from domainlab.utils.get_git_tag import get_git_tag - -from sklearn.metrics import ConfusionMatrixDisplay +from domainlab.utils.logger import Logger -class ExpModelPersistVisitor(): +class ExpModelPersistVisitor: """ This class couples with Task class attributes """ + model_dir = "saved_models" model_suffix = ".model" @@ -29,19 +32,22 @@ def __init__(self, host): """ self.host = host self.out = host.args.out - self.model_dir = os.path.join(self.out, - ExpModelPersistVisitor.model_dir) + self.model_dir = os.path.join(self.out, ExpModelPersistVisitor.model_dir) self.git_tag = get_git_tag() - self.task_name = self.host.task.get_na(self.host.args.tr_d, - self.host.args.te_d) - self.algo_name = self.host.args.aname + self.task_name = self.host.task.get_na(self.host.args.tr_d, self.host.args.te_d) + self.algo_name = self.host.args.model self.seed = self.host.args.seed self.model_name = self.mk_model_na(self.git_tag) - self.model_path = os.path.join(self.model_dir, - self.model_name + - ExpModelPersistVisitor.model_suffix) + self.model_path = os.path.join( + self.model_dir, self.model_name + ExpModelPersistVisitor.model_suffix + ) Path(os.path.dirname(self.model_path)).mkdir(parents=True, exist_ok=True) + self.model = copy.deepcopy(self.host.trainer.model) + # although deepcopy in contructor is expensive, but + # execute copy.deepcopy(self.host.trainer.model) after training will cause thread lock + # if self.host.trainer has tensorboard writer, see + # https://github.com/marrlab/DomainLab/issues/673 def mk_model_na(self, tag=None, dd_cut=19): """ @@ -52,17 +58,24 @@ def mk_model_na(self, tag=None, dd_cut=19): suffix_t = str(datetime.datetime.now())[:dd_cut].replace(" ", "_") suffix_t = suffix_t.replace("-", "md_") suffix_t = suffix_t.replace(":", "_") - list4mname = [self.task_name, - self.algo_name, - tag, suffix_t, - "seed", - str(self.seed)] + list4mname = [ + self.task_name, + self.algo_name, + tag, + suffix_t, + "seed", + str(self.seed), + ] # the sequence of components (e.g. seed in the last place) # in model name is not crutial model_name = "_".join(list4mname) if self.host.args.debug: model_name = "debug_" + model_name - print("model name:", model_name) + slurm = os.environ.get("SLURM_JOB_ID") + if slurm: + model_name = model_name + "_" + slurm + logger = Logger.get_logger() + logger.info(f"model name: {model_name}") return model_name def save(self, model, suffix=None): @@ -90,13 +103,26 @@ def remove(self, suffix=None): def load(self, suffix=None): """ load pre-defined model name from disk + the save function is the same class so to ensure load will ways work """ path = self.model_path if suffix is not None: path = "_".join([self.model_path, suffix]) - model = copy.deepcopy(self.host.trainer.model) - model.load_state_dict(torch.load(path, map_location="cpu")) - return model + # due to tensorboard writer in trainer.scheduler, + # copy.deepcopy(self.host.trainer.model) will cause thread lock + # see https://github.com/marrlab/DomainLab/issues/673 + self.model.load_state_dict(torch.load(path, map_location="cpu")) + # without separate self.model and self.model_suffixed, + # it will cause accuracy inconsistent problems since the content of self.model + # can be overwritten when the current function is called another time and self.model + # is not deepcopied + # However, deepcopy is also problematic when it is executed too many times + return copy.deepcopy(self.model) + # instead of deepcopy, one could also have multiple copies of model in constructor, but this + # does not adhere the lazy principle. + + def clean_up(self): + self.host.clean_up() class AggWriter(ExpModelPersistVisitor): @@ -104,6 +130,7 @@ class AggWriter(ExpModelPersistVisitor): 1. aggregate results to text file. 2. all dependencies are in the constructor """ + def __init__(self, host): super().__init__(host) self.agg_tag = self.host.args.aggtag @@ -135,13 +162,14 @@ def get_cols(self): """ epos_name = "epos" dict_cols = { - "algo": self.algo_name, - epos_name: None, - "seed": self.seed, - "aggtag": self.agg_tag, - # algorithm configuration for instance - "mname": "mname_" + self.model_name, - "commit": "commit_" + self.git_tag} + "algo": self.algo_name, + epos_name: None, + "seed": self.seed, + "aggtag": self.agg_tag, + # algorithm configuration for instance + "mname": "mname_" + self.model_name, + "commit": "commit_" + self.git_tag, + } return dict_cols, epos_name def _gen_line(self, dict_metric): @@ -162,9 +190,10 @@ def get_fpath(self, dirname="aggrsts"): for writing and reading, the same function is called to ensure name change in the future will not break the software """ - list4fname = [self.task_name, - self.exp_tag, - ] + list4fname = [ + self.task_name, + self.exp_tag, + ] fname = "_".join(list4fname) + ".csv" if self.debug: fname = "_".join(["debug_agg", fname]) @@ -177,8 +206,9 @@ def to_file(self, str_line): """ file_path = self.get_fpath() Path(os.path.dirname(file_path)).mkdir(parents=True, exist_ok=True) - print("results aggregation path:", file_path) - with open(file_path, 'a', encoding="utf8") as f_h: + logger = Logger.get_logger() + logger.info(f"results aggregation path: {file_path}") + with open(file_path, "a", encoding="utf8") as f_h: print(str_line, file=f_h) def confmat_to_file(self, confmat, confmat_filename): @@ -197,8 +227,11 @@ def confmat_to_file(self, confmat, confmat_filename): # @FIXME: still we want to have mname_ as a variable defined in some # configuration file in the future. confmat_filename = confmat_filename.removeprefix("mname_") - file_path = os.path.join(os.path.dirname(file_path), f"{confmat_filename}_conf_mat.png") - print("confusion matrix saved in file: ", file_path) + file_path = os.path.join( + os.path.dirname(file_path), f"{confmat_filename}_conf_mat.png" + ) + logger = Logger.get_logger() + logger.info(f"confusion matrix saved in file: {file_path}") disp.figure_.savefig(file_path) @@ -207,20 +240,46 @@ class ExpProtocolAggWriter(AggWriter): AggWriter tailored to experimental protocol Output contains additionally index, exp task, te_d and params. """ + def get_cols(self): """columns""" epos_name = "epos" dict_cols = { "param_index": self.host.args.param_index, - "task": self.host.args.benchmark_task_name, + "method": self.host.args.benchmark_task_name, + "mname": "mname_" + self.model_name, + "commit": "commit_" + self.git_tag, "algo": self.algo_name, epos_name: None, "te_d": self.host.args.te_d, "seed": self.seed, - "params": f"\"{self.host.args.params}\"", + "params": f'"{self.host.args.params}"', } return dict_cols, epos_name - def get_fpath(self, dirname="aggrsts"): + def get_fpath(self, dirname=None): """filepath""" - return self.host.args.result_file + if dirname is None: + return self.host.args.result_file + return super().get_fpath(dirname) + + def confmat_to_file(self, confmat, confmat_filename): + """Save confusion matrix as a figure + + Args: + confmat: confusion matrix. + """ + path4file = self.get_fpath() + index = os.path.basename(path4file) + path4file = os.path.dirname(os.path.dirname(path4file)) + # if prefix does not exist, string remain unchanged. + confmat_filename = confmat_filename.removeprefix("mname_") + path4file = os.path.join(path4file, "confusion_matrix") + os.makedirs(path4file, exist_ok=True) + file_path = os.path.join(path4file, f"{index}.txt") + with open(file_path, "a", encoding="utf8") as f_h: + print(confmat_filename, file=f_h) + for line in np.matrix(confmat): + np.savetxt(f_h, line, fmt="%.2f") + logger = Logger.get_logger() + logger.info(f"confusion matrix saved in file: {file_path}") diff --git a/domainlab/exp_protocol/aggregate_results.py b/domainlab/exp_protocol/aggregate_results.py new file mode 100644 index 000000000..d67cf5a0a --- /dev/null +++ b/domainlab/exp_protocol/aggregate_results.py @@ -0,0 +1,49 @@ +""" +Functions to join the csv result files generate by different jobs of the benchmarks into +a single csv file. +""" + +import os +from typing import List + +from domainlab.utils.generate_benchmark_plots import gen_benchmark_plots + + +def agg_results(input_files: List[str], output_file: str): + """ + Aggregrates the results of the snakemake benchmark. + + Combines csv files with identical columns into a single csv file. + + :param input_files: List of csv files with identical header. + :param output_file: Output csv file. + """ + os.makedirs(os.path.dirname(output_file), exist_ok=True) + has_header = False + # logger = Logger.get_logger() + # logger.debug(f"exp_results={input.exp_results}") + with open(output_file, "w") as out_stream: + for res in input_files: + with open(res, "r") as in_stream: + if has_header: + # skip header line + in_stream.readline() + else: + out_stream.writelines(in_stream.readline()) + has_header = True + # write results to common file. + out_stream.writelines(in_stream.readlines()) + + +def agg_from_directory(input_dir: str, output_file: str): + """Aggregates all results from a directory. Used to aggregate partial results.""" + file_list = [input_dir + os.sep + f for f in os.listdir(input_dir)] + agg_results(file_list, output_file) + + +def agg_main(bm_dir: str, skip_plotting: bool = False): + """Aggregates partial results and generate plots.""" + agg_output = f"{bm_dir}/results.csv" + agg_input = f"{bm_dir}/rule_results" + agg_from_directory(agg_input, agg_output) + gen_benchmark_plots(agg_output, f"{bm_dir}/graphics", skip_plotting) diff --git a/domainlab/exp_protocol/benchmark.smk b/domainlab/exp_protocol/benchmark.smk index df2f0a3a2..fcc9eb4f3 100644 --- a/domainlab/exp_protocol/benchmark.smk +++ b/domainlab/exp_protocol/benchmark.smk @@ -1,5 +1,11 @@ +# config variable (dictionary) is defined by snakemake framework which include all entries in the yaml file +# to add entries for variable "config" do snakemake --config new_key=value +# e.g. snakemake --config yaml_file=$CONFIGFILE +import os import sys from pathlib import Path +import pandas as pd + try: config_path = workflow.configfiles[0] @@ -13,27 +19,49 @@ except IndexError: sys.path.insert(0, Path(workflow.basedir).parent.parent.as_posix()) - envvars: - "DOMAINLAB_CUDA_START_SEED" + "DOMAINLAB_CUDA_START_SEED", + "DOMAINLAB_CUDA_HYPERPARAM_SEED", + "NUMBER_GPUS" def experiment_result_files(_): """Lists all expected i.csv""" - from domainlab.utils.hyperparameter_sampling import is_task - # count tasks - num_sample_tasks = 0 - num_nonsample_tasks = 0 - for key, val in config.items(): - if is_task(val): - if 'hyperparameters' in val.keys(): - num_sample_tasks += 1 - else: - num_nonsample_tasks += 1 - # total number of hyperparameter samples - total_num_params = config['num_param_samples'] * num_sample_tasks + num_nonsample_tasks - print(f"total_num_params={total_num_params}") - print(f"={config['num_param_samples']} * {num_sample_tasks} + {num_nonsample_tasks}") + from domainlab.utils.hyperparameter_sampling import is_dict_with_key + from domainlab.utils.logger import Logger + from domainlab.utils.hyperparameter_gridsearch import \ + sample_gridsearch + + logger = Logger.get_logger() + if 'mode' in config.keys(): + if config['mode'] == 'grid': + # hyperparameters are sampled using gridsearch + # in this case we don't know how many samples we will get beforehand + # straigt oreward solution: do a grid sampling and count samples + samples = sample_gridsearch(config) + total_num_params = samples.shape[0] + logger.info(f"total_num_params={total_num_params} for gridsearch") + else: + # in case of random sampling it is possible to compute the number + # of samples from the information in the yaml file + + # count tasks + num_sample_tasks = 0 + num_nonsample_tasks = 0 + for key, val in config.items(): + if is_dict_with_key(val, "model"): + if 'hyperparameters' in val.keys(): + num_sample_tasks += 1 + else: + if 'shared' in val.keys(): + num_sample_tasks += 1 + else: + num_nonsample_tasks += 1 + # total number of hyperparameter samples + total_num_params = config['num_param_samples'] * num_sample_tasks + num_nonsample_tasks + logger.info(f"total_num_params={total_num_params} for random sampling") + logger.info(f"={config['num_param_samples']} * {num_sample_tasks} + {num_nonsample_tasks}") + return [f"{config['output_dir']}/rule_results/{i}.csv" for i in range(total_num_params)] @@ -44,9 +72,36 @@ rule parameter_sampling: expand("{path}", path=config_path) output: dest=expand("{output_dir}/hyperparameters.csv", output_dir=config["output_dir"]) + params: + sampling_seed=os.environ["DOMAINLAB_CUDA_HYPERPARAM_SEED"] run: from domainlab.utils.hyperparameter_sampling import sample_hyperparameters - sample_hyperparameters(config, str(output.dest)) + from domainlab.utils.hyperparameter_gridsearch import sample_gridsearch + + # for gridsearch there is no random component, therefore no + # random seed is needed + if 'mode' in config.keys(): # type(config)=dict + if config['mode'] == 'grid': + sample_gridsearch(config,str(output.dest)) + # for random sampling we need to consider a random seed + else: + sampling_seed_str = params.sampling_seed + if isinstance(sampling_seed_str, str) and (len(sampling_seed_str) > 0): + # hash will keep integer intact and hash strings to random seed + # hased integer is signed and usually too big, random seed only + # allowed to be in [0, 2^32-1] + # if the user input is number, then hash will not change the value, + # so we recommend the user to use number as start seed + if sampling_seed_str.isdigit(): + sampling_seed = int(sampling_seed_str) + else: + sampling_seed = abs(hash(sampling_seed_str)) % (2 ** 32) + elif 'sampling_seed' in config.keys(): + sampling_seed = config['sampling_seed'] + else: + sampling_seed = None + + sample_hyperparameters(config, str(output.dest), sampling_seed) rule run_experiment: @@ -62,6 +117,8 @@ rule run_experiment: )) params: start_seed_str=os.environ["DOMAINLAB_CUDA_START_SEED"] + resources: + nvidia_gpu=1 run: from domainlab.exp_protocol.run_experiment import run_experiment # import sys @@ -71,13 +128,20 @@ rule run_experiment: # except Exception as ex: # pos = None # start_seed = sys.argv[pos+1] - + num_gpus_str=os.environ["NUMBER_GPUS"] start_seed_str = params.start_seed_str if isinstance(start_seed_str, str) and (len(start_seed_str) > 0): # hash will keep integer intact and hash strings to random seed - start_seed = hash(start_seed_str) + # hased integer is signed and usually too big, random seed only + # allowed to be in [0, 2^32-1] + # if the user input is number, then hash will not change the value, + # so we recommend the user to use number as start seed + if start_seed_str.isdigit(): + start_seed = int(start_seed_str) + else: + start_seed = abs(hash(start_seed_str)) % (2 ** 32) else: - start_seed = None + start_seed = None # use start seed defined in benchmark yaml configuration file # {index} defines wildcards named index index = int(expand(wildcards.index)[0]) # :param config: dictionary from the benchmark yaml @@ -86,7 +150,9 @@ rule run_experiment: # currently this correspond to the line number in the csv file, or row number # in the resulting pandas dataframe # :param out_file: path to the output csv - run_experiment(config,str(input.param_file),index,str(output.out_file), start_seed) + num_gpus = int(num_gpus_str) + run_experiment(config, str(input.param_file), index,str(output.out_file), + start_seed, num_gpus=num_gpus) rule agg_results: @@ -96,52 +162,12 @@ rule agg_results: output: out_file=expand("{output_dir}/results.csv", output_dir=config["output_dir"]) run: - import os - out_file = str(output.out_file) - os.makedirs(os.path.dirname(out_file), exist_ok=True) - has_header = False - # print(f"exp_results={input.exp_results}") - with open(out_file, 'w') as out_stream: - for res in input.exp_results: - with open(res, 'r') as in_stream: - if has_header: - # skip header line - in_stream.readline() - else: - out_stream.writelines(in_stream.readline()) - has_header = True - # write results to common file. - out_stream.writelines(in_stream.readlines()) - - -rule agg_partial_results: - input: - dir=expand("{output_dir}/rule_results", output_dir=config["output_dir"]) - params: - out_file=rules.agg_results.output.out_file - run: - import os - out_file = str(params.out_file) - os.makedirs(os.path.dirname(out_file), exist_ok=True) - has_header = False - # print(f"exp_results={input.exp_results}") - with open(out_file, 'w') as out_stream: - for res in os.listdir(input.dir): - if not res.endswith('.csv'): - # skip non-csv file entries - continue - with open(res, 'r') as in_stream: - if has_header: - # skip header line - in_stream.readline() - else: - out_stream.writelines(in_stream.readline()) - has_header = True - # write results to common file. - out_stream.writelines(in_stream.readlines()) + from domainlab.exp_protocol.aggregate_results import agg_results + agg_results(list(input.exp_results), str(output.out_file)) rule gen_plots: + # depends on previous rules of agg_(partial_)results input: res_file=rules.agg_results.output.out_file output: diff --git a/domainlab/exp_protocol/run_experiment.py b/domainlab/exp_protocol/run_experiment.py index 846360e33..81cdd091f 100644 --- a/domainlab/exp_protocol/run_experiment.py +++ b/domainlab/exp_protocol/run_experiment.py @@ -2,17 +2,20 @@ Runs one task for a single hyperparameter sample for each leave-out-domain and each random seed. """ -import gc import ast -import warnings +import copy +import gc +import numpy as np import pandas as pd import torch -from domainlab.arg_parser import mk_parser_main -from domainlab.compos.exp.exp_cuda_seed import set_seed -from domainlab.compos.exp.exp_main import Exp -from domainlab.compos.exp.exp_utils import ExpProtocolAggWriter +from domainlab.arg_parser import apply_dict_to_args, mk_parser_main +from domainlab.exp.exp_cuda_seed import set_seed +from domainlab.exp.exp_main import Exp +from domainlab.exp.exp_utils import ExpProtocolAggWriter +from domainlab.utils.hyperparameter_sampling import G_METHOD_NA +from domainlab.utils.logger import Logger def load_parameters(file: str, index: int) -> tuple: @@ -24,44 +27,34 @@ def load_parameters(file: str, index: int) -> tuple: param_df = pd.read_csv(file, index_col=0) row = param_df.loc[index] params = ast.literal_eval(row.params) - return row.task, params + # row.task has nothing to do with DomainLab task, it is + # benchmark task which correspond to one algorithm + return row[G_METHOD_NA], params -def apply_dict_to_args(args, data: dict, extend=False, flag_warn=False): +def convert_dict2float(dict_in): """ - Tries to apply the data to the args dict of DomainLab. - Unknown keys are silently ignored as long as - extend is not set. - # FIXME: do we have a test to ensure args dict from - # domainlab really got what is passed from "data" dict? + convert scientific notation from 1e5 to 10000 """ - arg_dict = args.__dict__ - for key, value in data.items(): - if (key in arg_dict) or extend: - if isinstance(value, list): - cur_val = arg_dict.get(key, None) - if not isinstance(cur_val, list): - if cur_val is not None: - # @FIXME: should we warn or raise Error? - warnings.warn(f"input dictionary value is list, \ - however, in DomainLab args, we have {cur_val}, \ - going to overrite to list") - arg_dict[key] = [] - arg_dict[key].extend(value) - else: - arg_dict[key] = value - else: - if flag_warn: - warnings.warn(f"{key} does not exist in DomainLab, ignoring!") + dict_out = copy.deepcopy(dict_in) + for key, val in dict_out.items(): + if isinstance(val, str): + try: + val_float = float(val) + dict_out[key] = val_float + except: + pass + return dict_out def run_experiment( - config: dict, - param_file: str, - param_index: int, - out_file: str, - start_seed=None, - misc=None, + config: dict, + param_file: str, + param_index: int, + out_file: str, + start_seed=None, + misc=None, + num_gpus=1, ): """ Runs the experiment several times: @@ -81,51 +74,114 @@ def run_experiment( # FIXME: we might want to run the experiment using commandline arguments """ + if misc is None: misc = {} - task, hyperparameters = load_parameters(param_file, param_index) - # print("\n*******************************************************************") - # print(f"{task}, param_index={param_index}, params={hyperparameters}") - # print("*******************************************************************\n") - misc['result_file'] = out_file - misc['params'] = hyperparameters - misc['benchmark_task_name'] = task - misc['param_index'] = param_index - misc['keep_model'] = False - misc['no_dump'] = True + str_algo_as_task, hyperparameters = load_parameters(param_file, param_index) + logger = Logger.get_logger() + logger.debug( + "\n*******************************************************************" + ) + logger.debug( + f"{str_algo_as_task}, param_index={param_index}, params={hyperparameters}" + ) + logger.debug( + "*******************************************************************\n" + ) + misc["result_file"] = out_file + misc["params"] = hyperparameters + misc["benchmark_task_name"] = str_algo_as_task + misc["param_index"] = param_index + misc["keep_model"] = False parser = mk_parser_main() args = parser.parse_args(args=[]) - apply_dict_to_args(args, config) - apply_dict_to_args(args, config[task]) + args_algo_specific = config[str_algo_as_task].copy() + if "hyperparameters" in args_algo_specific: + del args_algo_specific["hyperparameters"] + args_domainlab_common_raw = config.get("domainlab_args", {}) + args_domainlab_common = convert_dict2float(args_domainlab_common_raw) + # check if some of the hyperparameters are already specified + # in args_domainlab_common or args_algo_specific + if ( + np.intersect1d( + list(args_algo_specific.keys()), list(hyperparameters.keys()) + ).shape[0] + > 0 + ): + logger.error( + f"the hyperparameter " + f"{np.intersect1d(list(args_algo_specific.keys()), list(hyperparameters.keys()))}" + f" has already been fixed to a value in the algorithm section." + ) + raise RuntimeError( + f"the hyperparameter " + f"{np.intersect1d(list(args_algo_specific.keys()), list(hyperparameters.keys()))}" + f" has already been fixed to a value in the algorithm section." + ) + if ( + np.intersect1d( + list(args_domainlab_common.keys()), list(hyperparameters.keys()) + ).shape[0] + > 0 + ): + logger.error( + f"the hyperparameter " + f"{np.intersect1d(list(args_algo_specific.keys()), list(hyperparameters.keys()))}" + f" has already been fixed to a value in the domainlab_args section." + ) + raise RuntimeError( + f"the hyperparameter " + f"{np.intersect1d(list(args_algo_specific.keys()), list(hyperparameters.keys()))}" + f" has already been fixed to a value in the domainlab_args section." + ) + apply_dict_to_args(args, args_domainlab_common) + args_algo_specific_scientific_notation = convert_dict2float(args_algo_specific) + apply_dict_to_args(args, args_algo_specific_scientific_notation, extend=True) apply_dict_to_args(args, hyperparameters) apply_dict_to_args(args, misc, extend=True) + gpu_ind = param_index % num_gpus + args.device = str(gpu_ind) if torch.cuda.is_available(): torch.cuda.init() - print("before experiment loop: ") - print(torch.cuda.memory_summary()) + logger.info("before experiment loop: ") + logger.info(str(torch.cuda.memory_summary())) if start_seed is None: - start_seed = config['startseed'] - end_seed = config['endseed'] + start_seed = config["startseed"] + end_seed = config["endseed"] else: - end_seed = start_seed + (config['endseed'] - config['startseed']) - - for te_d in config['test_domains']: - args.te_d = te_d - for seed in range(start_seed, end_seed + 1): + end_seed = start_seed + (config["endseed"] - config["startseed"]) + for seed in range(start_seed, end_seed + 1): + for te_d in config["test_domains"]: + args.te_d = te_d set_seed(seed) args.seed = seed - if torch.cuda.is_available(): - print(torch.cuda.memory_summary()) + try: + if torch.cuda.is_available(): + logger.info("before experiment starts") + logger.info(str(torch.cuda.memory_summary())) + except KeyError as ex: + logger.error(str(ex)) + args.lr = float(args.lr) + # <=' not supported between instances of 'float' and 'str exp = Exp(args=args, visitor=ExpProtocolAggWriter) - if not misc.get('testing', False): + # NOTE: if key "testing" is set in benchmark, then do not execute + # experiment + if not misc.get("testing", False): exp.execute() + try: + if torch.cuda.is_available(): + logger.info("before torch memory clean up") + logger.info(str(torch.cuda.memory_summary())) + except KeyError as ex: + logger.error(str(ex)) del exp torch.cuda.empty_cache() gc.collect() try: if torch.cuda.is_available(): - print(torch.cuda.memory_summary()) + logger.info("after torch memory clean up") + logger.info(str(torch.cuda.memory_summary())) except KeyError as ex: - print(ex) + logger.error(str(ex)) diff --git a/domainlab/mk_exp.py b/domainlab/mk_exp.py new file mode 100644 index 000000000..6123df8c4 --- /dev/null +++ b/domainlab/mk_exp.py @@ -0,0 +1,33 @@ +""" +make an experiment +""" +from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp + + +def mk_exp(task, model, trainer: str, test_domain: str, batchsize: int, nocu=False): + """ + Creates a custom experiment. The user can specify the input parameters. + + Input Parameters: + - task: create a task to a custom dataset by importing "mk_task_dset" function from + "domainlab.tasks.task_dset". For more explanation on the input params refer to the + documentation found in "domainlab.tasks.task_dset.py". + - model: create a model [NameOfModel] by importing "mk_[NameOfModel]" function from + "domainlab.models.model_[NameOfModel]". For a concrete example and explanation of the input + params refer to the documentation found in "domainlab.models.model_[NameOfModel].py" + - trainer: string, + - test_domain: string, + - batch size: int + + Returns: experiment + """ + str_arg = ( + f"--model=apimodel --trainer={trainer} --te_d={test_domain} --bs={batchsize}" + ) + if nocu: + str_arg += " --nocu" + parser = mk_parser_main() + conf = parser.parse_args(str_arg.split()) + exp = Exp(conf, task, model=model) + return exp diff --git a/domainlab/models/a_model.py b/domainlab/models/a_model.py index 326a68100..beb867167 100644 --- a/domainlab/models/a_model.py +++ b/domainlab/models/a_model.py @@ -6,17 +6,68 @@ from torch import nn +from domainlab import g_list_model_penalized_reg_agg + class AModel(nn.Module, metaclass=abc.ABCMeta): """ operations that all models (classification, segmentation, seq2seq) """ - def cal_loss(self, tensor_x, tensor_y, tensor_d, others=None): + + def __init__(self): + super().__init__() + self._decoratee = None + self.list_d_tr = None + self.visitor = None + self._net_invar_feat = None + + def extend(self, model): + """ + extend the loss of the decoratee + """ + self._decoratee = model + self.reset_feature_extractor(model.net_invar_feat) + + @property + def metric4msel(self): + """ + metric for model selection + """ + raise NotImplementedError + + @property + def multiplier4task_loss(self): + """ + the multiplier for task loss is default to 1 except for vae family models + """ + return 1.0 + + def cal_loss(self, tensor_x, tensor_y, tensor_d=None, others=None): """ calculate the loss """ - return self.cal_task_loss(tensor_x, tensor_y) + \ - self.cal_reg_loss(tensor_x, tensor_y, tensor_d, others) + list_loss, list_multiplier = self.cal_reg_loss( + tensor_x, tensor_y, tensor_d, others + ) + loss_reg = self.list_inner_product(list_loss, list_multiplier) + loss_task_alone = self.cal_task_loss(tensor_x, tensor_y) + loss_task = self.multiplier4task_loss * loss_task_alone + return loss_task + loss_reg, list_loss, loss_task_alone + + def list_inner_product(self, list_loss, list_multiplier): + """ + compute inner product between list of regularization loss and multiplier + - the length of the list is the number of regularizers + - for each element of the list: the first dimension of the tensor is mini-batch + return value of list_inner_product should keep the minibatch structure, thus aggregation + here only aggregate along the list + """ + list_tuple = zip(list_loss, list_multiplier) + list_penalized_reg = [mtuple[0] * mtuple[1] for mtuple in list_tuple] + tensor_batch_penalized_loss = g_list_model_penalized_reg_agg(list_penalized_reg) + # return value of list_inner_product should keep the minibatch structure, thus aggregation + # here only aggregate along the list + return tensor_batch_penalized_loss @abc.abstractmethod def cal_task_loss(self, tensor_x, tensor_y): @@ -29,10 +80,28 @@ def cal_task_loss(self, tensor_x, tensor_y): """ @abc.abstractmethod + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): + """ + task independent regularization loss for domain generalization + """ + def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): """ task independent regularization loss for domain generalization """ + loss_reg, mu = self._extend_loss(tensor_x, tensor_y, tensor_d, others) + loss_reg_, mu_ = self._cal_reg_loss(tensor_x, tensor_y, tensor_d, others) + if loss_reg is not None: + return loss_reg_ + loss_reg, mu_ + mu + return loss_reg_, mu_ + + def _extend_loss(self, tensor_x, tensor_y, tensor_d, others=None): + """ + combine losses from two models + """ + if self._decoratee is not None: + return self._decoratee.cal_reg_loss(tensor_x, tensor_y, tensor_d, others) + return None, None def forward(self, tensor_x, tensor_y, tensor_d, others=None): """forward. @@ -42,3 +111,70 @@ def forward(self, tensor_x, tensor_y, tensor_d, others=None): :param d: """ return self.cal_loss(tensor_x, tensor_y, tensor_d, others) + + def extract_semantic_feat(self, tensor_x): + """ + extract semantic feature (not domain feature), note that + extract semantic feature is an action, it is more general than + calling a static network(module)'s forward function since + there are extra action like reshape the tensor + """ + if self._decoratee is not None: + return self._decoratee.extract_semantic_feat(tensor_x) + feat = self._net_invar_feat(tensor_x) + return feat + + @property + def net_invar_feat(self): + """ + if exist, return a neural network for extracting invariant features + """ + return self._net_invar_feat + + def reset_feature_extractor(self, net): + """ + for two models to share the same neural network, the feature extractor has to be reset + for classification, both feature extractor and classifier has to be reset + """ + # note if net is None, which means the decoratee does not have net_invar_feat (can be + # because there is tensor reshape during forward pass, which can not be represented + # by a static neural network, in this case, we simply set self._net_invar_feat to be + # None + self._net_invar_feat = net + self.reset_aux_net() + + def reset_aux_net(self): + """ + after feature extractor being reset, the input dim of other networks like domain + classification will also change (for commandline usage only) + """ + # by default doing nothing + + def save(self, suffix=None): + """ + persist model to disk + """ + if self.visitor is None: + return + self.visitor.save(self, suffix) + return + + def load(self, suffix=None): + """ + load model from disk + """ + if self.visitor is None: + return None + return self.visitor.load(suffix) + + def set_saver(self, visitor): + self.visitor = visitor + + def dset_decoration_args_algo(self, args, ddset): + """ + decorate dataset to get extra entries in load item, for instance, jigen need permutation index + this parent class function delegate decoration to its decoratee + """ + if self._decoratee is not None: + return self._decoratee.dset_decoration_args_algo(args, ddset) + return ddset diff --git a/domainlab/models/a_model_classif.py b/domainlab/models/a_model_classif.py index cae714835..1917f752e 100644 --- a/domainlab/models/a_model_classif.py +++ b/domainlab/models/a_model_classif.py @@ -3,26 +3,52 @@ """ import abc +import math + import numpy as np +import pandas as pd import torch -from torch import nn as nn +from torch import nn from torch.nn import functional as F from domainlab.models.a_model import AModel -from domainlab.utils.utils_class import store_args -from domainlab.utils.utils_classif import get_label_na, logit2preds_vpic +from domainlab.utils.logger import Logger from domainlab.utils.perf import PerfClassif from domainlab.utils.perf_metrics import PerfMetricClassif -from rich import print as rprint -import pandas as pd +from domainlab.utils.utils_class import store_args +from domainlab.utils.utils_classif import get_label_na, logit2preds_vpic + +try: + from backpack import extend +except: + backpack = None + +loss_cross_entropy_extended = extend(nn.CrossEntropyLoss(reduction="none")) class AModelClassif(AModel, metaclass=abc.ABCMeta): """ operations that all classification model should have """ + match_feat_fun_na = "cal_logit_y" + def extend(self, model): + super().extend(model) + self._net_classifier = model.net_classifier + + @property + def metric4msel(self): + return "acc" + + @property + def net_classifier(self): + return self._net_classifier + + @net_classifier.setter + def net_classifier(self, net_classifier): + self._net_classifier = net_classifier + def create_perf_obj(self, task): """ for classification, dimension of target can be quieried from task @@ -30,50 +56,61 @@ def create_perf_obj(self, task): self.perf_metric = PerfMetricClassif(task.dim_y) return self.perf_metric - def cal_perf_metric(self, loader_tr, device, loader_te=None): - """ - classification performance matric - """ - metric_te = None - metric_tr_pool = self.perf_metric.cal_metrics(self, loader_tr, device) - confmat = metric_tr_pool.pop("confmat") - print("pooled train domains performance:") - rprint(metric_tr_pool) - print("confusion matrix:") - print(pd.DataFrame(confmat)) - metric_tr_pool["confmat"] = confmat - # test set has no domain label, so can be more custom - if loader_te is not None: - metric_te = self.perf_metric.cal_metrics(self, loader_te, device) - confmat = metric_te.pop("confmat") - print("out of domain test performance:") - rprint(metric_te) - print("confusion matrix:") - print(pd.DataFrame(confmat)) - metric_te["confmat"] = confmat - return metric_te + def cal_perf_metric(self, loader, device): + """ + classification performance metric + """ + metric = None + with torch.no_grad(): + if loader is not None: + metric = self.perf_metric.cal_metrics(self, loader, device) + confmat = metric.pop("confmat") + logger = Logger.get_logger() + logger.info("scalar performance:") + logger.info(str(metric)) + logger.debug("confusion matrix:") + logger.debug(pd.DataFrame(confmat)) + metric["confmat"] = confmat + return metric def evaluate(self, loader_te, device): """ for classification task, use the current model to cal acc """ acc = PerfClassif.cal_acc(self, loader_te, device) - print("before training, model accuracy:", acc) + logger = Logger.get_logger() + logger.info(f"before training, model accuracy: {acc}") + + def extract_semantic_feat(self, tensor_x): + """ + flatten the shape of feature tensor from super() + """ + feat_tensor = super().extract_semantic_feat(tensor_x) + feat = feat_tensor.reshape(feat_tensor.shape[0], -1) + return feat - @abc.abstractmethod def cal_logit_y(self, tensor_x): """ calculate the logit for softmax classification """ + feat = self.extract_semantic_feat(tensor_x) + logits = self.net_classifier(feat) + return logits @store_args - def __init__(self, list_str_y, list_d_tr=None): + def __init__(self, **kwargs): """ :param list_str_y: list of fixed order, each element is a class label """ super().__init__() + for key, value in kwargs.items(): + if key == "list_str_y": + list_str_y = value + if key == "net_classifier": + net_classifier = value + self.list_str_y = list_str_y - self.list_d_tr = list_d_tr + self._net_classifier = net_classifier self.perf_metric = None self.loss4gen_adv = nn.KLDivLoss(size_average=False) @@ -117,32 +154,74 @@ def cal_task_loss(self, tensor_x, tensor_y): y_target = tensor_y else: _, y_target = tensor_y.max(dim=1) - lc_y = F.cross_entropy(logit_y, y_target, reduction="none") + lc_y = loss_cross_entropy_extended(logit_y, y_target) + # cross entropy always return a scalar, no need for inside instance reduction return lc_y - def pred2file(self, loader_te, device, - filename='path_prediction.txt', flag_pred_scalar=False): + def pred2file(self, loader_te, device, filename, metric_te, spliter="#"): """ pred2file dump predicted label to file as sanity check """ self.eval() model_local = self.to(device) - for _, (x_s, y_s, *_, path) in enumerate(loader_te): + logger = Logger.get_logger() + for _, (x_s, y_s, *_, path4instance) in enumerate(loader_te): x_s, y_s = x_s.to(device), y_s.to(device) _, prob, *_ = model_local.infer_y_vpicn(x_s) - # print(path) - list_pred_list = prob.tolist() - list_label_list = y_s.tolist() - if flag_pred_scalar: - list_pred_list = [np.asarray(pred).argmax() for pred in list_pred_list] - list_label_list = [np.asarray(label).argmax() for label in list_label_list] - # label belongs to data - list_pair_path_pred = list(zip(path, list_label_list, list_pred_list)) - with open(filename, 'a', encoding="utf8") as handle_file: - for pair in list_pair_path_pred: - # 1:-1 removes brackets of tuple - print(str(pair)[1:-1], file=handle_file) - print("prediction saved in file ", filename) + list_pred_prob_list = prob.tolist() + list_target_list = y_s.tolist() + list_target_scalar = [ + np.asarray(label).argmax() for label in list_target_list + ] + tuple_zip = zip(path4instance, list_target_scalar, list_pred_prob_list) + list_pair_path_pred = list(tuple_zip) + with open(filename, "a", encoding="utf8") as handle_file: + for list4one_obs_path_prob_target in list_pair_path_pred: + list_str_one_obs_path_target_predprob = [ + str(ele) for ele in list4one_obs_path_prob_target + ] + str_line = (" " + spliter + " ").join( + list_str_one_obs_path_target_predprob + ) + str_line = str_line.replace("[", "") + str_line = str_line.replace("]", "") + print(str_line, file=handle_file) + logger.info(f"prediction saved in file {filename}") + file_acc = self.read_prediction_file(filename, spliter) + acc_metric_te = metric_te["acc"] + flag1 = math.isclose(file_acc, acc_metric_te, rel_tol=1e-9, abs_tol=0.01) + acc_raw1 = PerfClassif.cal_acc(self, loader_te, device) + acc_raw2 = PerfClassif.cal_acc(self, loader_te, device) + flag_raw_consistency = math.isclose( + acc_raw1, acc_raw2, rel_tol=1e-9, abs_tol=0.01 + ) + flag2 = math.isclose(file_acc, acc_raw1, rel_tol=1e-9, abs_tol=0.01) + if not (flag1 & flag2 & flag_raw_consistency): + str_info = ( + f"inconsistent acc: \n" + f"prediction file acc generated using the current model is {file_acc} \n" + f"input torchmetric acc to the current function: {acc_metric_te} \n" + f"raw acc 1 {acc_raw1} \n" + f"raw acc 2 {acc_raw2} \n" + ) + raise RuntimeError(str_info) + return file_acc + + def read_prediction_file(self, filename, spliter): + """ + check if the written fiel could calculate acc + """ + with open(filename, "r", encoding="utf8") as handle_file: + list_lines = [line.strip().split(spliter) for line in handle_file] + count_correct = 0 + for line in list_lines: + list_prob = [float(ele) for ele in line[2].split(",")] + if np.array(list_prob).argmax() == int(line[1]): + count_correct += 1 + acc = count_correct / len(list_lines) + logger = Logger.get_logger() + logger.info(f"accuracy from prediction file {acc}") + return acc def cal_loss_gen_adv(self, x_natural, x_adv, vec_y): """ @@ -158,6 +237,10 @@ def cal_loss_gen_adv(self, x_natural, x_adv, vec_y): loss_adv_gen = self.loss4gen_adv(prob_adv, prob_natural) return loss_adv_gen + loss_adv_gen_task.sum() - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - return 0 - + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): + """ + for ERM to adapt to the interface of other regularized learners + """ + device = tensor_x.device + bsize = tensor_x.shape[0] + return [torch.zeros(bsize).to(device)], [0.0] diff --git a/domainlab/models/args_jigen.py b/domainlab/models/args_jigen.py index 90965ce12..91c2c90ae 100644 --- a/domainlab/models/args_jigen.py +++ b/domainlab/models/args_jigen.py @@ -1,19 +1,29 @@ """ hyper-parameters for JiGen """ + + def add_args2parser_jigen(parser): """ hyper-parameters for JiGen """ - parser.add_argument('--nperm', type=int, default=31, - help='number of permutations') - parser.add_argument('--pperm', type=float, default=0.7, - help='probability of permutating the tiles \ - of an image') - parser.add_argument('--jigen_ppath', type=str, default=None, - help='npy file path to load numpy array with each row being \ + parser.add_argument("--nperm", type=int, default=31, help="number of permutations") + parser.add_argument( + "--pperm", + type=float, + default=0.1, + help="probability of permutating the tiles \ + of an image", + ) + parser.add_argument( + "--jigen_ppath", + type=str, + default=None, + help="npy file path to load numpy array with each row being \ permutation index, if not None, nperm and grid_len has to agree \ - with the number of row and columns of the input array') - parser.add_argument('--grid_len', type=int, default=3, - help='length of image in tile unit') + with the number of row and columns of the input array", + ) + parser.add_argument( + "--grid_len", type=int, default=3, help="length of image in tile unit" + ) return parser diff --git a/domainlab/models/args_vae.py b/domainlab/models/args_vae.py index 5fd22aa69..4d56f96b5 100644 --- a/domainlab/models/args_vae.py +++ b/domainlab/models/args_vae.py @@ -1,54 +1,76 @@ def add_args2parser_vae(parser): - parser.add_argument('--zd_dim', type=int, default=64, - help='size of latent space for domain') - parser.add_argument('--zx_dim', type=int, default=0, - help='size of latent space for unobserved') - parser.add_argument('--zy_dim', type=int, default=64, - help='size of latent space for class') + parser.add_argument( + "--zd_dim", type=int, default=64, help="diva: size of latent space for domain" + ) + parser.add_argument( + "--zx_dim", + type=int, + default=0, + help="diva: size of latent space for unobserved", + ) + parser.add_argument( + "--zy_dim", + type=int, + default=64, + help="diva, hduva: size of latent space for class", + ) # HDUVA - parser.add_argument('--topic_dim', type=int, default=3, - help='dim latent space for topic') + parser.add_argument( + "--topic_dim", type=int, default=3, help="hduva: number of topics" + ) - parser.add_argument('--topic_h_dim', type=int, default=8, - help='dim latent space for topic') + parser.add_argument( + "--nname_encoder_x2topic_h", + type=str, + default=None, + help="hduva: network from image to topic distribution", + ) - parser.add_argument('--img_h_dim', type=int, default=8, - help='dim latent space for topic') + parser.add_argument( + "--npath_encoder_x2topic_h", + type=str, + default=None, + help="hduva: network from image to topic distribution", + ) - parser.add_argument('--nname_topic_distrib_img2topic', - type=str, default=None, - help='network from image to topic distribution') - parser.add_argument('--npath_topic_distrib_img2topic', - type=str, default=None, - help='network from image to topic distribution') - - parser.add_argument('--nname_encoder_sandwich_layer_img2h4zd', - type=str, default=None, - help='network from image to topic distribution') - parser.add_argument('--npath_encoder_sandwich_layer_img2h4zd', - type=str, default=None, - help='network from image to topic distribution') + parser.add_argument( + "--nname_encoder_sandwich_x2h4zd", + type=str, + default=None, + help="hduva: network from image and topic to zd", + ) + parser.add_argument( + "--npath_encoder_sandwich_x2h4zd", + type=str, + default=None, + help="hduva: network from image and topic to zd", + ) # ERM, ELBO - parser.add_argument('--gamma_y', type=float, default=None, - help='multiplier for y classifier') - parser.add_argument('--gamma_d', type=float, default=None, - help='multiplier for d classifier from zd') - - + parser.add_argument( + "--gamma_y", + type=float, + default=None, + help="diva, hduva: multiplier for y classifier", + ) + parser.add_argument( + "--gamma_d", + type=float, + default=None, + help="diva: multiplier for d classifier from zd", + ) # Beta VAE part - parser.add_argument('--beta_t', type=float, default=1., - help='multiplier for KL topic') - parser.add_argument('--beta_d', type=float, default=1., - help='multiplier for KL d') - parser.add_argument('--beta_x', type=float, default=1., - help='multiplier for KL x') - parser.add_argument('--beta_y', type=float, default=1., - help='multiplier for KL y') - # - - parser.add_argument('-w', '--warmup', type=int, default=100, - help='number of epochs for hyper-parameter warm-up. \ - Set to 0 to turn warmup off.') + parser.add_argument( + "--beta_t", type=float, default=1.0, help="hduva: multiplier for KL topic" + ) + parser.add_argument( + "--beta_d", type=float, default=1.0, help="diva: multiplier for KL d" + ) + parser.add_argument( + "--beta_x", type=float, default=1.0, help="diva: multiplier for KL x" + ) + parser.add_argument( + "--beta_y", type=float, default=1.0, help="diva, hduva: multiplier for KL y" + ) return parser diff --git a/domainlab/models/interface_vae_xyd.py b/domainlab/models/interface_vae_xyd.py new file mode 100644 index 000000000..2a587b677 --- /dev/null +++ b/domainlab/models/interface_vae_xyd.py @@ -0,0 +1,47 @@ +""" +Base Class for XYD VAE +""" +import torch +import torch.distributions as dist + +from domainlab.utils.utils_class import store_args + + +class InterfaceVAEXYD: + """ + Interface (without constructor and inheritance) for XYD VAE + """ + + def init(self): + self.chain_node_builder.init_business(self.zd_dim, self.zx_dim, self.zy_dim) + self.i_c = self.chain_node_builder.i_c + self.i_h = self.chain_node_builder.i_h + self.i_w = self.chain_node_builder.i_w + self._init_components() + + def _init_components(self): + """ + q(z|x) + p(zy) + q_{classif}(zy) + """ + self.add_module("encoder", self.chain_node_builder.build_encoder()) + self.add_module("decoder", self.chain_node_builder.build_decoder()) + self.add_module( + "net_p_zy", + self.chain_node_builder.construct_cond_prior(self.dim_y, self.zy_dim), + ) + + def init_p_zx4batch(self, batch_size, device): + """ + 1. Generate pytorch distribution object. + 2. To be called by trainer + + :param batch_size: + :param device: + """ + # p(zx): isotropic gaussian + zx_p_loc = torch.zeros(batch_size, self.zx_dim).to(device) + zx_p_scale = torch.ones(batch_size, self.zx_dim).to(device) + p_zx = dist.Normal(zx_p_loc, zx_p_scale) + return p_zx diff --git a/domainlab/models/model_custom.py b/domainlab/models/model_custom.py index 2c05f4582..6d3771ef2 100644 --- a/domainlab/models/model_custom.py +++ b/domainlab/models/model_custom.py @@ -8,42 +8,9 @@ class AModelCustom(AModelClassif): """AModelCustom.""" - - def __init__(self, list_str_y, list_str_d=None): - """__init__. - :param net: - :param list_str_y: - :param list_str_d: - """ - super().__init__(list_str_y, list_str_d) - - @property @abc.abstractmethod def dict_net_module_na2arg_na(self): """dict_net_module_na2arg_na. A dictionary with the key being the pytorch module name and value being the commandline argument name """ - raise NotImplementedError - - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - raise NotImplementedError - - def infer_y_vpicn(self, tensor): - """ - :param tensor: input - :return: - - v - vector of one-hot class label - - p - vector of probability - - i - class label index - - c - confidence: maximum probability - - n - list of name of class - """ - with torch.no_grad(): - logit_y = self.cal_logit_y(tensor) - vec_one_hot, prob, ind, confidence = logit2preds_vpic(logit_y) - na_class = get_label_na(ind, self.list_str_y) - return vec_one_hot, prob, ind, confidence, na_class diff --git a/domainlab/models/model_dann.py b/domainlab/models/model_dann.py index 7ec2ba1e9..2abd3feda 100644 --- a/domainlab/models/model_dann.py +++ b/domainlab/models/model_dann.py @@ -1,10 +1,27 @@ +""" +construct feature extractor, task neural network (e.g. classification) and domain classification +network +""" from torch.nn import functional as F +from domainlab import g_str_cross_entropy_agg from domainlab.compos.nn_zoo.net_adversarial import AutoGradFunReverseMultiply from domainlab.models.a_model_classif import AModelClassif -def mk_dann(parent_class=AModelClassif): - """Instantiate a Deep Adversarial Net (DAN) model + +def mk_dann(parent_class=AModelClassif, **kwargs): + """ + Instantiate a Deep Adversarial Net (DAN) model + + Details: + The model is trained to solve two tasks: + 1. Standard image classification. + 2. Domain classification. + Here for, a feature extractor is adversarially trained to minimize the loss of the image + classifier and maximize the loss of the domain classifier. + For more details, see: + Ganin, Yaroslav, et al. "Domain-adversarial training of neural networks." + The journal of machine learning research 17.1 (2016): 2096-2030. Args: parent_class (AModel, optional): Class object determining the task @@ -12,44 +29,80 @@ def mk_dann(parent_class=AModelClassif): Returns: ModelDAN: model inheriting from parent class + + Input Parameters: + list_str_y: list of labels, + list_d_tr: list of training domains + alpha: total_loss = task_loss + $$\\alpha$$ * domain_classification_loss, + net_encoder: neural network to extract the features (input: training data), + net_classifier: neural network (input: output of net_encoder; output: label prediction), + net_discriminator: neural network (input: output of net_encoder; + output: prediction of training domain) + + Usage: + For a concrete example, see: + https://github.com/marrlab/DomainLab/blob/master/tests/test_mk_exp_dann.py """ + class ModelDAN(parent_class): """ anonymous """ - def __init__(self, list_str_y, list_str_d, - alpha, net_encoder, net_classifier, net_discriminator): - super().__init__(list_str_y, list_str_d) + + def __init__( + self, + list_d_tr, + alpha, + net_encoder, + net_discriminator, + builder=None, + ): + """ + See documentation above in mk_dann() function + """ + super().__init__(**kwargs) + self.list_d_tr = list_d_tr self.alpha = alpha - self.net_encoder = net_encoder - self.net_classifier = net_classifier + self._net_invar_feat = net_encoder self.net_discriminator = net_discriminator + self.builder = builder + + def reset_aux_net(self): + """ + reset auxilliary neural network: domain classifier + """ + if self.builder is None: + return + self.net_discriminator = self.builder.reset_aux_net( + self.extract_semantic_feat + ) def hyper_update(self, epoch, fun_scheduler): """hyper_update. :param epoch: - :param fun_scheduler: + :param fun_scheduler: the hyperparameter scheduler object """ - dict_rst = fun_scheduler(epoch) + dict_rst = fun_scheduler( + epoch + ) # the __call__ method of hyperparameter scheduler self.alpha = dict_rst["alpha"] def hyper_init(self, functor_scheduler): """hyper_init. :param functor_scheduler: """ - return functor_scheduler(alpha=self.alpha) + return functor_scheduler(trainer=None, alpha=self.alpha) - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - return self.net_classifier(self.net_encoder(tensor_x)) - - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - feat = self.net_encoder(tensor_x) - logit_d = self.net_discriminator( - AutoGradFunReverseMultiply.apply(feat, self.alpha)) + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others): + _ = others + _ = tensor_y + feat = self.extract_semantic_feat(tensor_x) + net_grad_additive_reverse = AutoGradFunReverseMultiply.apply( + feat, self.alpha + ) + logit_d = self.net_discriminator(net_grad_additive_reverse) _, d_target = tensor_d.max(dim=1) - lc_d = F.cross_entropy(logit_d, d_target, reduction="none") - return self.alpha*lc_d + lc_d = F.cross_entropy(logit_d, d_target, reduction=g_str_cross_entropy_agg) + return [lc_d], [self.alpha] + return ModelDAN diff --git a/domainlab/models/model_deep_all.py b/domainlab/models/model_deep_all.py deleted file mode 100644 index ad86a40df..000000000 --- a/domainlab/models/model_deep_all.py +++ /dev/null @@ -1,38 +0,0 @@ -from domainlab.models.a_model_classif import AModelClassif -from domainlab.utils.override_interface import override_interface - - -def mk_deepall(parent_class=AModelClassif): - """Instantiate a Deepall model - - Args: - parent_class (AModel, optional): - Class object determining the task type. Defaults to AModelClassif. - - Returns: - ModelDeepAlll: model inheriting from parent class - """ - class ModelDeepAll(parent_class): - """ - anonymous - """ - def __init__(self, net, list_str_y, list_str_d=None): - super().__init__(list_str_y, list_str_d) - self.add_module("net", net) - - @override_interface(AModelClassif) - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - logit_y = self.net(tensor_x) - return logit_y - - def forward(self, tensor_x, tensor_y, tensor_d, others=None): - return self.cal_loss(tensor_x, tensor_y, tensor_d) - - def cal_loss(self, tensor_x, tensor_y, tensor_d, others=None): - lc_y = self.cal_task_loss(tensor_x, tensor_y) - return lc_y - - return ModelDeepAll diff --git a/domainlab/models/model_diva.py b/domainlab/models/model_diva.py index c56c8f497..b67272784 100644 --- a/domainlab/models/model_diva.py +++ b/domainlab/models/model_diva.py @@ -4,40 +4,92 @@ import torch from torch.nn import functional as F +from domainlab import g_inst_component_loss_agg, g_str_cross_entropy_agg from domainlab.models.model_vae_xyd_classif import VAEXYDClassif from domainlab.utils.utils_class import store_args -def mk_diva(parent_class=VAEXYDClassif): +def mk_diva(parent_class=VAEXYDClassif, **kwargs): """ - DIVA with arbitrary task loss + Instantiate a domain invariant variational autoencoder (DIVA) with arbitrary task loss. + + Details: + This method is creating a generative model based on a variational autoencoder, which can + reconstruct the input images. Here for, three different encoders with latent variables are + trained, each representing a latent subspace for the domain, class and residual features + information, respectively. The latent subspaces serve for disentangling the respective + sources of variation. To reconstruct the input image, the three latent variables are fed + into a decoder. + Additionally, two classifiers are trained, which predict the domain and the class label. + For more details, see: + Ilse, Maximilian, et al. "Diva: Domain invariant variational autoencoders." + Medical Imaging with Deep Learning. PMLR, 2020. + + Args: + parent_class: Class object determining the task type. Defaults to VAEXYDClassif. + + Returns: + ModelDIVA: model inheriting from parent class. + + Input Parameters: + zd_dim: size of latent space for domain-specific information, + zy_dim: size of latent space for class-specific information, + zx_dim: size of latent space for residual variance, + chain_node_builder: creates the neural network specified by the user; object of the class + "VAEChainNodeGetter" (see domainlab/compos/vae/utils_request_chain_builder.py) + being initialized by entering a user request, + list_str_y: list of labels, + list_d_tr: list of training domains, + gamma_d: weighting term for d classifier, + gamma_y: weighting term for y classifier, + beta_d: weighting term for domain encoder, + beta_x: weighting term for residual variation encoder, + beta_y: weighting term for class encoder + + Usage: + For a concrete example, see: + https://github.com/marrlab/DomainLab/blob/master/tests/test_mk_exp_diva.py """ + class ModelDIVA(parent_class): """ DIVA """ + @store_args - def __init__(self, chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_d_tr, - gamma_d, gamma_y, - beta_d, beta_x, beta_y): + def __init__( + self, + chain_node_builder, + zd_dim, + zy_dim, + zx_dim, + list_d_tr, + gamma_d, + gamma_y, + beta_d, + beta_x, + beta_y, + multiplier_recon=1.0, + ): """ gamma: classification loss coefficient """ - super().__init__(chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_d_tr) + super().__init__(chain_node_builder, zd_dim, zy_dim, zx_dim, **kwargs) + self.list_d_tr = list_d_tr self.dim_d_tr = len(self.list_d_tr) if self.zd_dim > 0: self.add_module( "net_p_zd", self.chain_node_builder.construct_cond_prior( - self.dim_d_tr, self.zd_dim)) + self.dim_d_tr, self.zd_dim + ), + ) self.add_module( "net_classif_d", self.chain_node_builder.construct_classifier( - self.zd_dim, self.dim_d_tr)) + self.zd_dim, self.dim_d_tr + ), + ) def hyper_update(self, epoch, fun_scheduler): """hyper_update. @@ -51,17 +103,16 @@ def hyper_update(self, epoch, fun_scheduler): self.beta_x = dict_rst["beta_x"] def hyper_init(self, functor_scheduler): - """hyper_init. - :param functor_scheduler: """ - return functor_scheduler( - beta_d=self.beta_d, beta_y=self.beta_y, beta_x=self.beta_x) + initiate a scheduler object via class name and things inside this model - def get_list_str_y(self): - """get_list_str_y.""" - return self._list_str_y + :param functor_scheduler: the class name of the scheduler + """ + return functor_scheduler( + trainer=None, beta_d=self.beta_d, beta_y=self.beta_y, beta_x=self.beta_x + ) - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): q_zd, zd_q, q_zx, zx_q, q_zy, zy_q = self.encoder(tensor_x) logit_d = self.net_classif_d(zd_q) @@ -75,19 +126,37 @@ def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): z_concat = self.decoder.concat_ydx(zy_q, zd_q, zx_q) loss_recon_x, _, _ = self.decoder(z_concat, tensor_x) - zd_p_minus_zd_q = torch.sum( - p_zd.log_prob(zd_q) - q_zd.log_prob(zd_q), 1) - zx_p_minus_zx_q = torch.sum( - p_zx.log_prob(zx_q) - q_zx.log_prob(zx_q), 1) - zy_p_minus_zy_q = torch.sum( - p_zy.log_prob(zy_q) - q_zy.log_prob(zy_q), 1) + zd_p_minus_zd_q = g_inst_component_loss_agg( + p_zd.log_prob(zd_q) - q_zd.log_prob(zd_q), 1 + ) + # without aggregation, shape is [batchsize, zd_dim] + zx_p_minus_zx_q = torch.zeros_like(zd_p_minus_zd_q) + if self.zx_dim > 0: + # torch.sum will return 0 for empty tensor, + # torch.mean will return nan + zx_p_minus_zx_q = g_inst_component_loss_agg( + p_zx.log_prob(zx_q) - q_zx.log_prob(zx_q), 1 + ) + + zy_p_minus_zy_q = g_inst_component_loss_agg( + p_zy.log_prob(zy_q) - q_zy.log_prob(zy_q), 1 + ) _, d_target = tensor_d.max(dim=1) - lc_d = F.cross_entropy(logit_d, d_target, reduction="none") + lc_d = F.cross_entropy(logit_d, d_target, reduction=g_str_cross_entropy_agg) + + return [ + loss_recon_x, + zd_p_minus_zd_q, + zx_p_minus_zx_q, + zy_p_minus_zy_q, + lc_d, + ], [ + self.multiplier_recon, + -self.beta_d, + -self.beta_x, + -self.beta_y, + self.gamma_d, + ] - return loss_recon_x \ - - self.beta_d * zd_p_minus_zd_q \ - - self.beta_x * zx_p_minus_zx_q \ - - self.beta_y * zy_p_minus_zy_q \ - + self.gamma_d * lc_d return ModelDIVA diff --git a/domainlab/models/model_erm.py b/domainlab/models/model_erm.py new file mode 100644 index 000000000..6ee9c23f9 --- /dev/null +++ b/domainlab/models/model_erm.py @@ -0,0 +1,56 @@ +""" +Emperical risk minimization +""" +from domainlab.compos.nn_zoo.nn import LayerId +from domainlab.models.a_model_classif import AModelClassif +from domainlab.utils.override_interface import override_interface + +try: + from backpack import extend +except: + backpack = None + + +def mk_erm(parent_class=AModelClassif, **kwargs): + """ + Instantiate a Deepall (ERM) model + + Details: + Creates a model, which trains a neural network via standard empirical risk minimization + (ERM). The fact that the training data stems from different domains is neglected, as all + domains are pooled together during training. + + Args: + parent_class (AModel, optional): + Class object determining the task type. Defaults to AModelClassif. + + Returns: + ModelERM: model inheriting from parent class + + Input Parameters: + custom neural network, the output dimension must be the number of labels + + Usage: + For a concrete example, see: + https://github.com/marrlab/DomainLab/blob/tests/test_mk_exp_erm.py + """ + + class ModelERM(parent_class): + """ + anonymous + """ + + def __init__(self, net=None, net_feat=None): + if net is not None: + net_feat = net + kwargs["net_classifier"] = LayerId() + super().__init__(**kwargs) + self._net_invar_feat = net_feat + + def convert4backpack(self): + """ + convert the module to backpack for 2nd order gradients + """ + self._net_invar_feat = extend(self._net_invar_feat, use_converter=True) + self.net_classifier = extend(self.net_classifier, use_converter=True) + return ModelERM diff --git a/domainlab/models/model_hduva.py b/domainlab/models/model_hduva.py index 7f0de1031..61411982e 100644 --- a/domainlab/models/model_hduva.py +++ b/domainlab/models/model_hduva.py @@ -4,25 +4,68 @@ import torch from torch.distributions import Dirichlet +from domainlab import g_inst_component_loss_agg from domainlab.models.model_vae_xyd_classif import VAEXYDClassif from domainlab.utils.utils_class import store_args -def mk_hduva(parent_class=VAEXYDClassif): +def mk_hduva(parent_class=VAEXYDClassif, **kwargs): """ - Hierarchical Domain Unsupervised VAE with arbitrary task loss + Instantiate a Hierarchical Domain Unsupervised VAE (HDUVA) with arbitrary task loss. + + Details: + The created model builds on a generative approach within the framework of variational + autoencoders to facilitate generalization to new domains without supervision. HDUVA learns + representations that disentangle domain-specific information from class-label specific + information even in complex settings where domain structure is not observed during training. + Here for, latent variables are introduced, representing the information for the classes, + domains and the residual variance of the inputs, respectively. The domain structure is + modelled by a hierarchical level and another latent variable, denoted as topic. + Two encoder networks are trained. One for converting an image to be compatible with the + latent spaces of the domains and another one for converting an image to a topic + distribution. The overall objective is constructed by adding an additional weighted term to + the ELBO loss. One benefit of this model is that the domain information during training can + be incomplete. + For more details, see: Sun, Xudong, and Buettner, Florian. + "Hierarchical variational auto-encoding for unsupervised domain generalization." + arXiv preprint arXiv:2101.09436 (2021). + + Args: + parent_class: Class object determining the task type. Defaults to VAEXYDClassif. + + Returns: + ModelHDUVA: model inheriting from parent class. + + Input Parameters: + zd_dim: size of latent space for domain-specific information (int), + zy_dim: size of latent space for class-specific information (int), + zx_dim: size of latent space for residual variance (int, defaults to 0), + chain_node_builder: an object which can build different maps via neural network, + list_str_y: list of labels (list of strings), + gamma_d: weighting term for domain classificaiton loss + gamma_y: weighting term for additional term in ELBO loss (float), + beta_d: weighting term for the domain component of ELBO loss (float), + beta_x: weighting term for residual variation component of ELBO loss (float), + beta_y: weighting term for class component of ELBO loss (float), + beta_t: weighting term for the topic component of ELBO loss (float), + device: device to which the model should be moved (cpu or gpu), + topic_dim: size of latent space for topics (int, defaults to 3) """ + class ModelHDUVA(parent_class): """ Hierarchical Domain Unsupervised Variational Auto-Encoding """ + def hyper_update(self, epoch, fun_scheduler): """hyper_update. :param epoch: :param fun_scheduler: """ - dict_rst = fun_scheduler(epoch) + dict_rst = fun_scheduler( + epoch + ) # the __call__ function of hyper-para-scheduler object self.beta_d = dict_rst["beta_d"] self.beta_y = dict_rst["beta_y"] self.beta_x = dict_rst["beta_x"] @@ -32,58 +75,67 @@ def hyper_init(self, functor_scheduler): """hyper_init. :param functor_scheduler: """ + # calling the constructor of the hyper-parameter-scheduler class, so that this scheduler + # class build a dictionary {"beta_d":self.beta_d, "beta_y":self.beta_y} + # constructor signature is def __init__(self, **kwargs): return functor_scheduler( - beta_d=self.beta_d, beta_y=self.beta_y, beta_x=self.beta_x, - beta_t=self.beta_t) + trainer=None, + beta_d=self.beta_d, + beta_y=self.beta_y, + beta_x=self.beta_x, + beta_t=self.beta_t, + ) @store_args - def __init__(self, chain_node_builder, - zy_dim, zd_dim, - list_str_y, list_d_tr, - gamma_d, gamma_y, - beta_d, beta_x, beta_y, - beta_t, - device, - zx_dim=0, - topic_dim=3): - """ - """ - super().__init__(chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_d_tr) + def __init__( + self, + chain_node_builder, + zy_dim, + zd_dim, + gamma_d, + gamma_y, + beta_d, + beta_x, + beta_y, + beta_t, + device, + zx_dim=0, + topic_dim=3, + multiplier_recon=1.0): + """ """ + super().__init__(chain_node_builder, zd_dim, zy_dim, zx_dim, **kwargs) # topic to zd follows Gaussian distribution - self.add_module("net_p_zd", - self.chain_node_builder.construct_cond_prior( - self.topic_dim, self.zd_dim)) - + self.add_module( + "net_p_zd", + self.chain_node_builder.construct_cond_prior( + self.topic_dim, self.zd_dim + ), + ) + + # override interface def _init_components(self): """ q(z|x) p(zy) q_{classif}(zy) """ - self.add_module("encoder", self.chain_node_builder.build_encoder( - self.device, self.topic_dim)) - self.add_module("decoder", self.chain_node_builder.build_decoder( - self.topic_dim)) - self.add_module("net_p_zy", - self.chain_node_builder.construct_cond_prior( - self.dim_y, self.zy_dim)) - self.add_module("net_classif_y", - self.chain_node_builder.construct_classifier( - self.zy_dim, self.dim_y)) - - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - _, _, \ - _, _, \ - _, _, \ - _, zy_q = self.encoder(tensor_x) - logit_y = self.net_classif_y(zy_q) - return logit_y + self.add_module( + "encoder", + self.chain_node_builder.build_encoder(self.device, self.topic_dim), + ) + self.add_module( + "decoder", self.chain_node_builder.build_decoder(self.topic_dim) + ) + self.add_module( + "net_p_zy", + self.chain_node_builder.construct_cond_prior(self.dim_y, self.zy_dim), + ) + self.add_module( + "net_classif_y", + self.chain_node_builder.construct_classifier(self.zy_dim, self.dim_y), + ) + self._net_classifier = self.net_classif_y def init_p_topic_batch(self, batch_size, device): """ @@ -92,33 +144,45 @@ def init_p_topic_batch(self, batch_size, device): prior = Dirichlet(torch.ones(batch_size, self.topic_dim).to(device)) return prior - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): - q_topic, topic_q, \ - qzd, zd_q, \ - qzx, zx_q, \ - qzy, zy_q = self.encoder(tensor_x) + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d=None, others=None): + q_topic, topic_q, qzd, zd_q, qzx, zx_q, qzy, zy_q = self.encoder(tensor_x) batch_size = zd_q.shape[0] device = zd_q.device p_topic = self.init_p_topic_batch(batch_size, device) - # zx KL divergence - zx_p_minus_q = 0 - if self.zx_dim > 0: - p_zx = self.init_p_zx4batch(batch_size, device) - zx_p_minus_q = torch.sum(p_zx.log_prob(zx_q) - qzx.log_prob(zx_q), 1) - # @FIXME: does monte-carlo KL makes the performance unstable? # from torch.distributions import kl_divergence # zy KL divergence - p_zy = self.net_p_zy(tensor_y) - zy_p_minus_zy_q = torch.sum(p_zy.log_prob(zy_q) - qzy.log_prob(zy_q), 1) + + if (tensor_y.shape[-1] == 1) | (len(tensor_y.shape) == 1): + tensor_y_onehot = torch.nn.functional.one_hot( + tensor_y, num_classes=len(self.list_str_y) + ) + tensor_y_onehot = tensor_y_onehot.to(torch.float32) + else: + tensor_y_onehot = tensor_y + + p_zy = self.net_p_zy(tensor_y_onehot) + zy_p_minus_zy_q = g_inst_component_loss_agg( + p_zy.log_prob(zy_q) - qzy.log_prob(zy_q), 1 + ) + + # zx KL divergence + zx_p_minus_q = torch.zeros_like(zy_p_minus_zy_q) + if self.zx_dim > 0: + p_zx = self.init_p_zx4batch(batch_size, device) + zx_p_minus_q = g_inst_component_loss_agg( + p_zx.log_prob(zx_q) - qzx.log_prob(zx_q), 1 + ) # zd KL diverence p_zd = self.net_p_zd(topic_q) - zd_p_minus_q = torch.sum(p_zd.log_prob(zd_q) - qzd.log_prob(zd_q), 1) + zd_p_minus_q = g_inst_component_loss_agg( + p_zd.log_prob(zd_q) - qzd.log_prob(zd_q), 1 + ) # topic KL divergence # @FIXME: why topic is still there? @@ -127,10 +191,25 @@ def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): # reconstruction z_concat = self.decoder.concat_ytdx(zy_q, topic_q, zd_q, zx_q) loss_recon_x, _, _ = self.decoder(z_concat, tensor_x) - batch_loss = loss_recon_x \ - - self.beta_x * zx_p_minus_q \ - - self.beta_y * zy_p_minus_zy_q \ - - self.beta_d * zd_p_minus_q \ - - self.beta_t * topic_p_minus_q - return batch_loss + return [ + loss_recon_x, + zx_p_minus_q, + zy_p_minus_zy_q, + zd_p_minus_q, + topic_p_minus_q, + ], [ + self.multiplier_recon, + -self.beta_x, + -self.beta_y, + -self.beta_d, + -self.beta_t, + ] + + def extract_semantic_feat(self, tensor_x): + """ + :param tensor_x: + """ + zy_q_loc = self.encoder.infer_zy_loc(tensor_x) + return zy_q_loc + return ModelHDUVA diff --git a/domainlab/models/model_jigen.py b/domainlab/models/model_jigen.py index 884debbf2..8d08d9b1b 100644 --- a/domainlab/models/model_jigen.py +++ b/domainlab/models/model_jigen.py @@ -1,14 +1,31 @@ """ Jigen Model Similar to DANN model """ +import warnings + from torch.nn import functional as F +from domainlab import g_str_cross_entropy_agg +from domainlab.dsets.utils_wrapdset_patches import WrapDsetPatches from domainlab.models.a_model_classif import AModelClassif from domainlab.models.model_dann import mk_dann -def mk_jigen(parent_class=AModelClassif): - """Instantiate a JiGen model +def mk_jigen(parent_class=AModelClassif, **kwargs): + """ + Instantiate a JiGen model + + Details: + The model is trained to solve two tasks: + 1. Standard image classification; + 2. Source images are decomposed into grids of patches, which are then permuted. The task + is recovering the original image by predicting the right permutation of the patches; + + The (permuted) input data is first fed into a encoder neural network + and then into the two classification networks. + For more details, see: + Carlucci, Fabio M., et al. "Domain generalization by solving jigsaw puzzles." + Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019. Args: parent_class (AModel, optional): Class object determining the task @@ -16,28 +33,68 @@ def mk_jigen(parent_class=AModelClassif): Returns: ModelJiGen: model inheriting from parent class + + Input Parameters: + list_str_y: list of labels, + list_str_d: list of domains, + net_encoder: neural network (input: training data, standard and shuffled), + net_classifier_class: neural network (input: output of net_encoder; + output: label prediction), + net_classifier_permutation: neural network (input: output of net_encoder; + output: prediction of permutation index), + coeff_reg: total_loss = img_class_loss + coeff_reg * perm_task_loss + nperm: number of permutations to use, by default 31 + prob_permutation: probability of shuffling image tiles + + Usage: + For a concrete example, see: + https://github.com/marrlab/DomainLab/blob/master/tests/test_mk_exp_jigen.py """ - class_dann = mk_dann(parent_class) + + class_dann = mk_dann(parent_class, **kwargs) class ModelJiGen(class_dann): """ Jigen Model Similar to DANN model """ - def __init__(self, list_str_y, list_str_d, - net_encoder, - net_classifier_class, - net_classifier_permutation, - coeff_reg): - super().__init__(list_str_y, list_str_d, - alpha=coeff_reg, - net_encoder=net_encoder, - net_classifier=net_classifier_class, - net_discriminator=net_classifier_permutation) + + def __init__( + self, + net_encoder, + net_classifier_permutation, + coeff_reg, + n_perm=31, + prob_permutation=0.1): + super().__init__( + list_d_tr=None, + alpha=coeff_reg, + net_encoder=net_encoder, + net_discriminator=net_classifier_permutation, + ) self.net_encoder = net_encoder - self.net_classifier_class = net_classifier_class self.net_classifier_permutation = net_classifier_permutation + self.n_perm = n_perm + self.prob_perm = prob_permutation + + def dset_decoration_args_algo(self, args, ddset): + """ + JiGen need to shuffle the tiles of the original image + """ + # note if model is initialized via API, args might not agree with self.n_perm + # in this case, we just ignore args, since in model builder, self.n_perm is set + # via args as well + nperm = self.n_perm # ignore args since self.n_perm also set via args + pperm = self.prob_perm + ddset_new = WrapDsetPatches( + ddset, + num_perms2classify=nperm, + prob_no_perm=1 - pperm, + grid_len=args.grid_len, + ppath=args.jigen_ppath, + ) + return ddset_new - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): + def _cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others): """ JiGen don't need domain label but a pre-defined permutation index to calculate regularization loss @@ -47,13 +104,23 @@ def cal_reg_loss(self, tensor_x, tensor_y, tensor_d, others=None): which permutation has been used or no permutation has been used at all (which also has to be classified) """ - vec_perm_ind = tensor_d + _ = tensor_y + _ = tensor_d + if isinstance(others, list) or isinstance(others, tuple): + vec_perm_ind = others[0] + else: + vec_perm_ind = others # tensor_x can be either original image or tile-shuffled image - feat = self.net_encoder(tensor_x) + feat = self.extract_semantic_feat(tensor_x) logits_which_permutation = self.net_classifier_permutation(feat) # _, batch_target_scalar = vec_perm_ind.max(dim=1) batch_target_scalar = vec_perm_ind + batch_target_scalar = batch_target_scalar.to(tensor_x.device) loss_perm = F.cross_entropy( - logits_which_permutation, batch_target_scalar, reduction="none") - return self.alpha*loss_perm + logits_which_permutation, + batch_target_scalar, + reduction=g_str_cross_entropy_agg, + ) + return [loss_perm], [self.alpha] + return ModelJiGen diff --git a/domainlab/models/model_vae_xyd_classif.py b/domainlab/models/model_vae_xyd_classif.py index be1b9af43..381405946 100644 --- a/domainlab/models/model_vae_xyd_classif.py +++ b/domainlab/models/model_vae_xyd_classif.py @@ -1,65 +1,43 @@ """ -Base Class for XYD VAE +Base Class for XYD VAE Classify """ -import torch -import torch.distributions as dist - from domainlab.models.a_model_classif import AModelClassif +from domainlab.models.interface_vae_xyd import InterfaceVAEXYD from domainlab.utils.utils_class import store_args -class VAEXYDClassif(AModelClassif): +class VAEXYDClassif(AModelClassif, InterfaceVAEXYD): """ - Base Class for XYD VAE + Base Class for DIVA and HDUVA """ + @store_args - def __init__(self, chain_node_builder, - zd_dim, zy_dim, zx_dim, - list_str_y, list_str_d): + def __init__(self, chain_node_builder, zd_dim, zy_dim, zx_dim, **kwargs): """ :param chain_node_builder: constructed object """ - super().__init__(list_str_y, list_str_d) - self.chain_node_builder.init_business( - self.zd_dim, self.zx_dim, self.zy_dim) - self.i_c = self.chain_node_builder.i_c - self.i_h = self.chain_node_builder.i_h - self.i_w = self.chain_node_builder.i_w - self._init_components() + for key, value in kwargs.items(): + if key == "list_str_y": + list_str_y = value + super().__init__(net_classifier=None, list_str_y=list_str_y) + self.init() + self._net_classifier = self.net_classif_y - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ + def extract_semantic_feat(self, tensor_x): zy_q_loc = self.encoder.infer_zy_loc(tensor_x) - logit_y = self.net_classif_y(zy_q_loc) - return logit_y + return zy_q_loc - def _init_components(self): + @property + def multiplier4task_loss(self): """ - q(z|x) - p(zy) - q_{classif}(zy) + the multiplier for task loss is default to 1.0 except for vae family models """ - self.add_module("encoder", self.chain_node_builder.build_encoder()) - self.add_module("decoder", self.chain_node_builder.build_decoder()) - self.add_module("net_p_zy", - self.chain_node_builder.construct_cond_prior( - self.dim_y, self.zy_dim)) - self.add_module("net_classif_y", - self.chain_node_builder.construct_classifier( - self.zy_dim, self.dim_y)) + return self.gamma_y - def init_p_zx4batch(self, batch_size, device): - """ - 1. Generate pytorch distribution object. - 2. To be called by trainer - - :param batch_size: - :param device: - """ - # p(zx): isotropic gaussian - zx_p_loc = torch.zeros(batch_size, self.zx_dim).to(device) - zx_p_scale = torch.ones(batch_size, self.zx_dim).to(device) - p_zx = dist.Normal(zx_p_loc, zx_p_scale) - return p_zx + def _init_components(self): + super()._init_components() + self.add_module( + "net_classif_y", + self.chain_node_builder.construct_classifier(self.zy_dim, self.dim_y), + ) + # property setter only for other object, internally, one shoud use _net_classifier diff --git a/domainlab/models/wrapper_matchdg.py b/domainlab/models/wrapper_matchdg.py deleted file mode 100644 index dcf7dcbc1..000000000 --- a/domainlab/models/wrapper_matchdg.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Wrapper for MatchDG to conform of model class in DomainLab -""" -from domainlab.models.a_model_classif import AModelClassif - - -class ModelWrapMatchDGLogit(AModelClassif): - """ - Wrap an arbitrary model with interface:cal_logit_y - """ - def __init__(self, net, list_str_y, list_str_d=None): - super().__init__(list_str_y, list_str_d) - fun_name = AModelClassif.match_feat_fun_na - if not hasattr(net, fun_name): - raise RuntimeError( - "model to be wrapped must inherit base class ", - str(AModelClassif.__class__), - " with attribute:", fun_name) - self.net = net - - def cal_logit_y(self, tensor_x): - return self.net.cal_logit_y(tensor_x) - - def cal_loss(self, tensor_x, tensor_y, tensor_d=None, others=None): - return self.net.cal_loss(tensor_x, tensor_y, tensor_d) - - def cal_reg_loss(self, tensor_x, tensor_y, tensor_d=None, others=None): - return self.net.cal_loss(tensor_x, tensor_y, tensor_d) # @FIXME: this is wrong - - def forward(self, tensor_x): - """ - calculate features to be matched - """ - logit_y = self.net.cal_logit_y(tensor_x) # @FIXME: match other features instead of logit - return logit_y diff --git a/domainlab/tasks/__init__.py b/domainlab/tasks/__init__.py index 0ea68c8df..8c3e74e0b 100644 --- a/domainlab/tasks/__init__.py +++ b/domainlab/tasks/__init__.py @@ -1 +1,2 @@ from domainlab.tasks.task_folder_mk import mk_task_folder +from domainlab.tasks.zoo_tasks import get_task diff --git a/domainlab/tasks/a_task.py b/domainlab/tasks/a_task.py new file mode 100644 index 000000000..6eab450d7 --- /dev/null +++ b/domainlab/tasks/a_task.py @@ -0,0 +1,186 @@ +""" +Base class for Task +""" +import warnings +from abc import abstractmethod + +from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler +from domainlab.tasks.task_utils import parse_domain_id +from domainlab.utils.logger import Logger + + +class NodeTaskDG(AbstractChainNodeHandler): + """ + Domain Generalization Classification Task + """ + + def __init__(self, succ=None): + super().__init__(succ) + self._loader_tr = None + self._loader_te = None + self._loader_val = None + self._list_domains = None + self._list_domain_tr = None # versatile + self._name = None + self._args = None + self.dict_dset_all = {} # persist + self.dict_dset_tr = {} # versatile variable: which domains to use as training + self.dict_dset_te = {} # versatile + self.dict_dset_val = {} # versatile + self.dict_loader_tr = {} + self.dict_domain_class_count = {} + self.dim_d_tr = None # public, only used for diva + self._im_size = None + self._dict_domains2imgroot = {} + self._dict_domain_folder_name2class = ( + {} + ) # {"domain1": {"class1":car, "class2":dog}} + self._dict_domain_img_trans = {} + self.dict_att = {} + self.img_trans_te = None + self.dict_domain2imgroot = {} + self._dict_domain2filepath_list_im_tr = ( + {} + ) # {"photo": "xxx/yyy/file_of_path2imgs"} + self._dict_domain2filepath_list_im_val = {} + self._dict_domain2filepath_list_im_te = {} + self.dict_class_label_ind2name = None + self.conf_without_args() # configuration without init_business + + def conf_without_args(self): + """ + configuration without init_business + """ + + @abstractmethod + def init_business(self, args, trainer=None): + """ + construct task data loader + """ + + def get_list_domains(self): + """ + 1. get list of domain names + 2. better use method than property so new domains can be added + """ + return self._list_domains + + def set_list_domains(self, list_domains): + """ + setter for self._list_domains + """ + self._list_domains = list_domains + + @property + def isize(self): + """ + getter for input size: isize + """ + return self._im_size + + @isize.setter + def isize(self, im_size): + """ + setter for input size: isize + """ + self._im_size = im_size + + @property + def list_domain_tr(self): + """ + property getter of list of domains for this task + """ + if self._list_domain_tr is None: + raise RuntimeError("task not intialized!") + return self._list_domain_tr + + @property + def loader_tr(self): + """loader of mixed train domains""" + return self._loader_tr + + @property + def loader_val(self): + """loader of validation dataset on the training domains""" + return self._loader_val + + @property + def loader_te(self): + """loader of mixed test domains""" + return self._loader_te + + @property + def task_name(self): + """ + The basic name of the task, without configurations + """ + # @FIXME: hardcoded position:NodeTaskXXX + return type(self).__name__[8:].lower() + + def get_na(self, na_tr, na_te): + """ + task name appended with configurations + :param na_tr: training domain names + :param na_te: test domain names + """ + _, list_te = self.get_list_domains_tr_te(na_tr, na_te) + str_te = "_".join(list_te) + # train domain names are too long + return "_".join([self.task_name, "te", str_te]) + + def is_myjob(self, request): + """ + :param request: string + """ + return request == self.task_name + + def get_list_domains_tr_te(self, tr_id, te_id): + """ + For static DG task, get train and test domains list. + + :param tr_id: training domain ids; + int or str, or a list of int or str, or None; + if None, then assumed to be the complement of te_id. + :param te_id: test domain ids; + int or str, or a list of int or str; required. + :return: list of training domain names, list of test domain names. + """ + list_domains = self.get_list_domains() + + list_domain_te = parse_domain_id(te_id, list_domains) + assert set(list_domain_te).issubset(set(list_domains)) + + if tr_id is None: + list_domain_tr = [did for did in list_domains if did not in list_domain_te] + else: + list_domain_tr = parse_domain_id(tr_id, list_domains) + if not set(list_domain_tr).issubset(set(list_domains)): + raise RuntimeError( + f"training domain {list_domain_tr} is not \ + subset of available domains {list_domains}" + ) + + if set(list_domain_tr) & set(list_domain_te): + logger = Logger.get_logger() + logger.warn( + "The sets of training and test domains overlap -- " + "be aware of data leakage or training to the test!" + ) + warnings.warn( + "The sets of training and test domains overlap -- " + "be aware of data leakage or training to the test!", + RuntimeWarning, + ) + + self.dim_d_tr = len(list_domain_tr) + self._list_domain_tr = list_domain_tr + return list_domain_tr, list_domain_te + + def __str__(self): + """ + print the attribute of the task + """ + strout = "list of domains: \n" + strout += str(self.get_list_domains()) + strout += f"\n input tensor size: {self.isize}" + return strout diff --git a/domainlab/tasks/a_task_classif.py b/domainlab/tasks/a_task_classif.py index bd0e1196a..50ce926ca 100644 --- a/domainlab/tasks/a_task_classif.py +++ b/domainlab/tasks/a_task_classif.py @@ -2,156 +2,57 @@ Abstract class for TaskClassif """ import os -import warnings -from abc import abstractmethod, abstractproperty -from domainlab.compos.pcr.p_chain_handler import AbstractChainNodeHandler +from domainlab.tasks.a_task import NodeTaskDG from domainlab.tasks.utils_task import img_loader2dir -from domainlab.tasks.task_utils import parse_domain_id -class NodeTaskDGClassif(AbstractChainNodeHandler): +class NodeTaskDGClassif(NodeTaskDG): """ - Domain Generalization Classification Task + abstract class for classification task """ + def __init__(self, succ=None): - super().__init__(succ) - self._loader_tr = None - self._loader_te = None - self._loader_val = None - self._list_domains = None - self._list_domain_tr = None - self.dict_dset = {} - self.dict_dset_te = {} - self.dict_dset_val = {} - self.dict_domain_class_count = {} - self.dim_d_tr = None # public + # just for declaration of variables self._list_str_y = None - self._im_size = None - self._dict_domains2imgroot = {} - self._dict_domain_folder_name2class = {} # {"domain1": {"class1":car, "class2":dog}} - self._dict_domain_img_trans = {} - self._dict_domain2filepath_list_im = {} # {"photo": "xxx/yyy/file_of_path2imgs"} - self.dict_att = {} - self.img_trans_te = None + self._dim_y = None + # super() must come last instead of in the beginning + super().__init__(succ) - @abstractmethod - def init_business(self, args): + @property + def list_str_y(self): """ - construct loader with resampling - :param seed: random seed for resampling - :param bs: batch size - :param domain_na_tes: test domain names + getter for list_str_y """ + return self._list_str_y - @abstractmethod - def get_list_domains(self): + @list_str_y.setter + def list_str_y(self, list_str_y): """ - 1. get list of domain names - 2. better use method than property so new domains can be added + setter for list_str_y """ - raise NotImplementedError + self._list_str_y = list_str_y - @abstractproperty - def list_str_y(self): - raise NotImplementedError - - @abstractproperty - def isize(self): - """image channel, height, width""" - raise NotImplementedError - - ########################################################################### @property def dim_y(self): """classification dimension""" - return len(self.list_str_y) - - @property - def list_domain_tr(self): - """ - property getter of list of domains for this task - """ - if self._list_domain_tr is None: - raise RuntimeError("task not intialized!") - return self._list_domain_tr - - @property - def loader_tr(self): - """loader of mixed train domains""" - return self._loader_tr - - @property - def loader_val(self): - """loader of validation dataset on the training domains""" - return self._loader_val - - @property - def loader_te(self): - """loader of mixed test domains""" - return self._loader_te - - @property - def task_name(self): - """ - The basic name of the task, without configurations - """ - # @FIXME: hardcoded position - return type(self).__name__[8:].lower() + if self._dim_y is None: + if self.list_str_y is not None: + return len(self.list_str_y) + raise RuntimeError("attribute list_str_y not set yet") + return self._dim_y - def get_na(self, na_tr, na_te): + @dim_y.setter + def dim_y(self, dim_y): """ - task name appended with configurations - :param na_tr: training domain names - :param na_te: test domain names + setter for dim_y, for classification task, the number of labels to predict """ - _, list_te = self.get_list_domains_tr_te(na_tr, na_te) - str_te = "_".join(list_te) - # train domain names are too long - return "_".join([self.task_name, "te", str_te]) - - def is_myjob(self, request): - """ - :param request: string - """ - return request == self.task_name - - def get_list_domains_tr_te(self, tr_id, te_id): - """ - For static DG task, get train and test domains list. - - :param tr_id: training domain ids; - int or str, or a list of int or str, or None; - if None, then assumed to be the complement of te_id. - :param te_id: test domain ids; - int or str, or a list of int or str; required. - :return: list of training domain names, list of test domain names. - """ - list_domains = self.get_list_domains() - - list_domain_te = parse_domain_id(te_id, list_domains) - assert set(list_domain_te).issubset(set(list_domains)) - - if tr_id is None: - list_domain_tr = [did for did in list_domains if - did not in list_domain_te] - else: - list_domain_tr = parse_domain_id(tr_id, list_domains) - if not set(list_domain_tr).issubset(set(list_domains)): - raise RuntimeError( - f"training domain {list_domain_tr} is not \ - subset of available domains {list_domains}") - - if set(list_domain_tr) & set(list_domain_te): - warnings.warn( - "The sets of training and test domains overlap -- \ - be aware of data leakage or training to the test!", - RuntimeWarning - ) - - self.dim_d_tr = len(list_domain_tr) - self._list_domain_tr = list_domain_tr - return list_domain_tr, list_domain_te + if self.list_str_y is not None: + if len(self.list_str_y) is not dim_y: + raise RuntimeError( + f"dim y={dim_y} not equal to self.list_str_y={self.list_str_y}" + ) + self._dim_y = dim_y def sample_sav(self, root, batches=5, subfolder_na="task_sample"): """ @@ -159,15 +60,19 @@ def sample_sav(self, root, batches=5, subfolder_na="task_sample"): """ folder_na = os.path.join(root, self.task_name, subfolder_na) - img_loader2dir(self.loader_te, - list_domain_na=self.get_list_domains(), - list_class_na=self.list_str_y, - folder=folder_na, - batches=batches, - test=True) - - img_loader2dir(self.loader_tr, - list_domain_na=self.get_list_domains(), - list_class_na=self.list_str_y, - folder=folder_na, - batches=batches) + img_loader2dir( + self.loader_te, + list_domain_na=self.get_list_domains(), + list_class_na=self.list_str_y, + folder=folder_na, + batches=batches, + test=True, + ) + + img_loader2dir( + self.loader_tr, + list_domain_na=self.get_list_domains(), + list_class_na=self.list_str_y, + folder=folder_na, + batches=batches, + ) diff --git a/domainlab/tasks/b_task.py b/domainlab/tasks/b_task.py index 71a45dc5a..d8b778689 100644 --- a/domainlab/tasks/b_task.py +++ b/domainlab/tasks/b_task.py @@ -1,125 +1,72 @@ """ Use dictionaries to create train and test domain split """ -from collections import Counter - -import torch from torch.utils.data.dataset import ConcatDataset -from domainlab.tasks.a_task_classif import NodeTaskDGClassif -from domainlab.tasks.utils_task import (DsetDomainVecDecorator, mk_loader, - mk_onehot) +from domainlab.tasks.a_task import NodeTaskDG +from domainlab.tasks.utils_task import DsetDomainVecDecorator, mk_loader, mk_onehot -class NodeTaskDict(NodeTaskDGClassif): +class NodeTaskDict(NodeTaskDG): """ Use dictionaries to create train and test domain split """ - @property - def list_str_y(self): - return self._list_str_y - - @list_str_y.setter - def list_str_y(self, list_str_y): - self._list_str_y = list_str_y - - @property - def isize(self): - return self._im_size - - @isize.setter - def isize(self, im_size): - self._im_size = im_size - - def get_list_domains(self): - return self._list_domains - - def set_list_domains(self, list_domains): - """ - setter for self._list_domains - """ - self._list_domains = list_domains def get_dset_by_domain(self, args, na_domain, split=False): """ - each domain correspond to one dataset + each domain correspond to one dataset, must be implemented by child class """ - raise NotImplementedError + raise NotImplementedError # it is safe for each subclass to implement this def decorate_dset(self, model, args): """ dispatch re-organization of data flow to model """ - def init_business(self, args): + def init_business(self, args, trainer=None): """ create a dictionary of datasets """ - # @FIXME - from domainlab.algos.zoo_algos import AlgoBuilderChainNodeGetter - # ImportError: cannot import name 'AlgoBuilderChainNodeGetter' - # from partially initialized module 'domainlab.algos.zoo_algos' - # (most likely due to a circular import) - # (~/domainlab_master/domainlab/algos/zoo_algos.py) - node = AlgoBuilderChainNodeGetter(args)() - list_domain_tr, list_domain_te = self.get_list_domains_tr_te(args.tr_d, args.te_d) - self.dict_dset = {} + list_domain_tr, list_domain_te = self.get_list_domains_tr_te( + args.tr_d, args.te_d + ) + self.dict_dset_tr = {} self.dict_dset_val = {} dim_d = len(list_domain_tr) - for (ind_domain_dummy, na_domain) in enumerate(list_domain_tr): - # FIXME: specify either split = True or False - dset_tr, dset_val = self.get_dset_by_domain(args, na_domain) - # @FIXME: currently, different task has different default values for - # split, for TaskFolder split default to False, for mnist, split - # default to True - vec_domain = mk_onehot(dim_d, ind_domain_dummy) + for ind_domain_dummy, na_domain in enumerate(list_domain_tr): + dset_tr, dset_val = self.get_dset_by_domain( + args, na_domain, split=args.split + ) + vec_domain = mk_onehot(dim_d, ind_domain_dummy) # for diva, dann ddset_tr = DsetDomainVecDecorator(dset_tr, vec_domain, na_domain) ddset_val = DsetDomainVecDecorator(dset_val, vec_domain, na_domain) - ddset_tr = node.dset_decoration_args_algo(args, ddset_tr) - ddset_val = node.dset_decoration_args_algo(args, ddset_val) - self.dict_dset.update({na_domain: ddset_tr}) + if trainer is not None and hasattr(trainer, "dset_decoration_args_algo"): + ddset_tr = trainer.dset_decoration_args_algo(args, ddset_tr) + ddset_val = trainer.dset_decoration_args_algo(args, ddset_val) + if ( + trainer is not None + and trainer.model is not None + and hasattr(trainer.model, "dset_decoration_args_algo") + ): + ddset_tr = trainer.model.dset_decoration_args_algo(args, ddset_tr) + ddset_val = trainer.model.dset_decoration_args_algo(args, ddset_val) + self.dict_dset_tr.update({na_domain: ddset_tr}) + self.dict_loader_tr.update({na_domain: mk_loader(ddset_tr, args.bs)}) self.dict_dset_val.update({na_domain: ddset_val}) - ddset_mix = ConcatDataset(tuple(self.dict_dset.values())) + ddset_mix = ConcatDataset(tuple(self.dict_dset_tr.values())) self._loader_tr = mk_loader(ddset_mix, args.bs) ddset_mix_val = ConcatDataset(tuple(self.dict_dset_val.values())) - self._loader_val = mk_loader(ddset_mix_val, args.bs) + self._loader_val = mk_loader( + ddset_mix_val, args.bs, shuffle=False, drop_last=False + ) self.dict_dset_te = {} # No need to have domain Label for test for na_domain in list_domain_te: dset_te, *_ = self.get_dset_by_domain(args, na_domain, split=False) - # @FIXME: since get_dset_by_domain always return two datasets, + # NOTE: since get_dset_by_domain always return two datasets, # train and validation, this is not needed in test domain self.dict_dset_te.update({na_domain: dset_te}) dset_te = ConcatDataset(tuple(self.dict_dset_te.values())) - self._loader_te = mk_loader(dset_te, args.bs, drop_last=False) - self.count_domain_class() - - def count_domain_class(self): - """ - iterate all domains and count the class label distribution for each - return a double dictionary {"domain1": {"class1":3, "class2": 4,...}, ....} - """ - for key, dset in self.dict_dset.items(): - dict_class_count = self._count_class_one_hot(dset) - self.dict_domain_class_count[key] = dict_class_count - for key, dset in self.dict_dset_te.items(): - dict_class_count = self._count_class_one_hot(dset) - self.dict_domain_class_count[key] = dict_class_count - - def _count_class_one_hot(self, dset): - labels_count = torch.zeros(self.dim_y, dtype=torch.long) - for _, target, *_ in dset: - labels_count += target.long() - - list_count = list(labels_count.cpu().numpy()) - dict_class_count = {} - for name, count in zip(self.list_str_y, list_count): - dict_class_count[name] = count - return dict_class_count - - def _count_class(self, dset): # @FIXME: remove this - labels = dset.targets - class_dict = dict(Counter(labels)) - return class_dict + self._loader_te = mk_loader(dset_te, args.bs, shuffle=False, drop_last=False) diff --git a/domainlab/tasks/b_task_classif.py b/domainlab/tasks/b_task_classif.py new file mode 100644 index 000000000..15fbb911d --- /dev/null +++ b/domainlab/tasks/b_task_classif.py @@ -0,0 +1,43 @@ +""" +Use dictionaries to create train and test domain split +""" +import torch + +from domainlab.tasks.a_task_classif import NodeTaskDGClassif +from domainlab.tasks.b_task import NodeTaskDict + + +class NodeTaskDictClassif(NodeTaskDict, NodeTaskDGClassif): + """ + Use dictionaries to create train and test domain split + """ + + def init_business(self, args, trainer=None): + """ + create a dictionary of datasets + """ + super().init_business(args=args, trainer=trainer) + self.count_domain_class() + + def count_domain_class(self): + """ + iterate all domains and count the class label distribution for each + return a double dictionary {"domain1": {"class1":3, "class2": 4,...}, ....} + """ + for key, dset in self.dict_dset_tr.items(): + dict_class_count = self._count_class_one_hot(dset) + self.dict_domain_class_count[key] = dict_class_count + for key, dset in self.dict_dset_te.items(): + dict_class_count = self._count_class_one_hot(dset) + self.dict_domain_class_count[key] = dict_class_count + + def _count_class_one_hot(self, dset): + labels_count = torch.zeros(self.dim_y, dtype=torch.long) + for _, target, *_ in dset: + labels_count += target.long() + + list_count = list(labels_count.cpu().numpy()) + dict_class_count = {} + for name, count in zip(self.list_str_y, list_count): + dict_class_count[name] = count + return dict_class_count diff --git a/domainlab/tasks/task_dset.py b/domainlab/tasks/task_dset.py new file mode 100644 index 000000000..9c415ec5e --- /dev/null +++ b/domainlab/tasks/task_dset.py @@ -0,0 +1,67 @@ +""" +Use dictionaries to create train and test domain split +""" +from domainlab.tasks.b_task_classif import NodeTaskDictClassif # abstract class + + +def mk_task_dset( + isize, + taskna="task_custom", # name of the task + dim_y=None, + list_str_y=None, + parent=NodeTaskDictClassif, + succ=None, +): + """ + make a task via a dictionary of dataset where the key is domain + value is a tuple of dataset for training and dataset for + validation (can be identical to training) + """ + + class NodeTaskDset(parent): + """ + Use dictionaries to create train and test domain split + """ + + def conf_without_args(self): + """ + set member variables + """ + self._name = taskna + + if list_str_y is None and dim_y is None: + raise RuntimeError( + "arguments list_str_y and dim_y can not be both None!" + ) + + self.list_str_y = ( + list_str_y # list_str_y has to be initialized before dim_y + ) + self.dim_y = dim_y + + if self.list_str_y is None: + self.list_str_y = [f"class{ele}" for ele in range(0, self.dim_y)] + self.isize = isize + + def get_dset_by_domain(self, args, na_domain, split=False): + """ + each domain correspond to one dataset, must be implemented by child class + """ + return self.dict_dset_all[na_domain] + + def init_business(self, args, trainer=None): + """ + create a dictionary of datasets + """ + self.set_list_domains(list(self.dict_dset_all.keys())) + super().init_business(args, trainer) + + def add_domain(self, name, dset_tr, dset_val=None): + """ + add domain via, name, dataset and transformations + """ + self.dict_dset_all[name] = (dset_tr, dset_val) + # when add a new domain, change self state + self.set_list_domains(list(self.dict_dset_all.keys())) + + return NodeTaskDset(succ=succ) diff --git a/domainlab/tasks/task_folder.py b/domainlab/tasks/task_folder.py index 16811c4d5..94b0c134d 100644 --- a/domainlab/tasks/task_folder.py +++ b/domainlab/tasks/task_folder.py @@ -4,18 +4,22 @@ from torchvision import transforms from domainlab.dsets.dset_subfolder import DsetSubFolder -from domainlab.dsets.utils_data import (DsetInMemDecorator, - fun_img_path_loader_default, - mk_fun_label2onehot) -from domainlab.tasks.b_task import NodeTaskDict +from domainlab.dsets.utils_data import ( + DsetInMemDecorator, + fun_img_path_loader_default, + mk_fun_label2onehot, +) +from domainlab.tasks.b_task_classif import NodeTaskDictClassif from domainlab.tasks.utils_task import DsetClassVecDecoratorImgPath +from domainlab.utils.logger import Logger -class NodeTaskFolder(NodeTaskDict): +class NodeTaskFolder(NodeTaskDictClassif): """ create dataset by loading files from an organized folder then each domain correspond to one dataset """ + @property def dict_domain2imgroot(self): """ @@ -46,19 +50,22 @@ def extensions(self, str_format): def get_dset_by_domain(self, args, na_domain, split=False): if float(args.split): raise RuntimeError( - "this task does not support spliting training domain yet") + "this task does not support spliting training domain yet" + ) if self._dict_domain_img_trans: trans = self._dict_domain_img_trans[na_domain] if na_domain not in self.list_domain_tr: trans = self.img_trans_te else: trans = transforms.ToTensor() - dset = DsetSubFolder(root=self.dict_domain2imgroot[na_domain], - list_class_dir=self.list_str_y, - loader=fun_img_path_loader_default, - extensions=self.extensions, - transform=trans, - target_transform=mk_fun_label2onehot(len(self.list_str_y))) + dset = DsetSubFolder( + root=self.dict_domain2imgroot[na_domain], + list_class_dir=self.list_str_y, + loader=fun_img_path_loader_default, + extensions=self.extensions, + transform=trans, + target_transform=mk_fun_label2onehot(len(self.list_str_y)), + ) return dset, dset # @FIXME: validation by default set to be training set @@ -67,13 +74,15 @@ class NodeTaskFolderClassNaMismatch(NodeTaskFolder): when the folder names of the same class from different domains have different names """ + def get_dset_by_domain(self, args, na_domain, split=False): if float(args.split): raise RuntimeError( - "this task does not support spliting training domain yet") - print("reading domain:", na_domain) - domain_class_dirs = \ - self._dict_domain_folder_name2class[na_domain].keys() + "this task does not support spliting training domain yet" + ) + logger = Logger.get_logger() + logger.info(f"reading domain: {na_domain}") + domain_class_dirs = self._dict_domain_folder_name2class[na_domain].keys() if self._dict_domain_img_trans: trans = self._dict_domain_img_trans[na_domain] if na_domain not in self.list_domain_tr: @@ -82,20 +91,21 @@ def get_dset_by_domain(self, args, na_domain, split=False): trans = transforms.ToTensor() ext = None if self.extensions is None else self.extensions[na_domain] - dset = DsetSubFolder(root=self.dict_domain2imgroot[na_domain], - list_class_dir=list(domain_class_dirs), - loader=fun_img_path_loader_default, - extensions=ext, - transform=trans, - target_transform=mk_fun_label2onehot( - len(self.list_str_y))) + dset = DsetSubFolder( + root=self.dict_domain2imgroot[na_domain], + list_class_dir=list(domain_class_dirs), + loader=fun_img_path_loader_default, + extensions=ext, + transform=trans, + target_transform=mk_fun_label2onehot(len(self.list_str_y)), + ) # dset.path2imgs - dict_folder_name2class_global = \ - self._dict_domain_folder_name2class[na_domain] + dict_folder_name2class_global = self._dict_domain_folder_name2class[na_domain] dset = DsetClassVecDecoratorImgPath( - dset, dict_folder_name2class_global, self.list_str_y) + dset, dict_folder_name2class_global, self.list_str_y + ) # Always use the DsetInMemDecorator at the last step # since it does not have other needed attributes in bewteen if args.dmem: dset = DsetInMemDecorator(dset, na_domain) - return dset, dset # @FIXME: validation by default set to be training set + return dset, dset # @FIXME: validation by default set to be training set diff --git a/domainlab/tasks/task_folder_mk.py b/domainlab/tasks/task_folder_mk.py index cf23b2f09..5fad128da 100644 --- a/domainlab/tasks/task_folder_mk.py +++ b/domainlab/tasks/task_folder_mk.py @@ -4,22 +4,25 @@ from domainlab.tasks.task_folder import NodeTaskFolderClassNaMismatch -def mk_task_folder(extensions, - list_str_y, - dict_domain_folder_name2class, - dict_domain_img_trans, - img_trans_te, - isize, - dict_domain2imgroot, - taskna, - succ=None): +def mk_task_folder( + extensions, + list_str_y, + dict_domain_folder_name2class, + dict_domain_img_trans, + img_trans_te, + isize, + dict_domain2imgroot, + taskna, + succ=None, +): """ Make task by specifying each domain with folder structures :param extensions: Different Options: 1. a python dictionary with key as the domain name and value (str or tuple[str]) as the file extensions of the image. 2. a str or tuple[str] with file extensions for all domains. 3. None: in each domain all files with an extension in ('jpg', 'jpeg', 'png') are loaded. - :param list_str_y: a python list with user defined class name where + :param + list_str_y: a python list with user defined class name where the order of the list matters. :param dict_domain_folder_name2class: a python dictionary, with key as the user specified domain name, value as a dictionary to map the @@ -36,6 +39,7 @@ def mk_task_folder(extensions, names and values as the absolute path to each domain's data. :taskna: user defined task name """ + class NodeTaskFolderDummy(NodeTaskFolderClassNaMismatch): @property def task_name(self): @@ -44,7 +48,7 @@ def task_name(self): """ return taskna - def conf(self, args): + def conf_without_args(self): self.extensions = extensions self.list_str_y = list_str_y self._dict_domain_folder_name2class = dict_domain_folder_name2class @@ -54,7 +58,4 @@ def conf(self, args): self._dict_domain_img_trans = dict_domain_img_trans self.img_trans_te = img_trans_te - def init_business(self, args): - self.conf(args) - super().init_business(args) return NodeTaskFolderDummy(succ=succ) diff --git a/domainlab/tasks/task_mini_vlcs.py b/domainlab/tasks/task_mini_vlcs.py new file mode 100644 index 000000000..bea20ce8e --- /dev/null +++ b/domainlab/tasks/task_mini_vlcs.py @@ -0,0 +1,61 @@ +""" +test task for image size 224 +""" +import os + +from torchvision import transforms + +from domainlab.tasks.task_folder_mk import mk_task_folder +from domainlab.tasks.utils_task import ImSize + +path_this_file = os.path.dirname(os.path.realpath(__file__)) + + +def addtask2chain(chain): + """ + given a chain of responsibility for task selection, add another task into the chain + """ + new_chain = mk_task_folder( + extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, + list_str_y=["chair", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "stuhl": "chair"}, + "sun": {"vehicle": "car", "sofa": "chair"}, + "labelme": {"drive": "car", "sit": "chair"}, + }, + dict_domain_img_trans={ + "caltech": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "sun": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "labelme": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + }, + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": os.path.join( + path_this_file, + os.path.normpath("../"), + os.path.normpath("zdata/vlcs_mini/caltech/"), + ), + "sun": os.path.join( + path_this_file, + os.path.normpath("../"), + os.path.normpath("zdata/vlcs_mini/sun/"), + ), + "labelme": os.path.join( + path_this_file, + os.path.normpath("../"), + os.path.normpath("zdata/vlcs_mini/labelme/"), + ), + }, + taskna="mini_vlcs", + succ=chain, + ) + return new_chain diff --git a/domainlab/tasks/task_mnist_color.py b/domainlab/tasks/task_mnist_color.py index 9fadd60a8..f01d77eab 100644 --- a/domainlab/tasks/task_mnist_color.py +++ b/domainlab/tasks/task_mnist_color.py @@ -3,18 +3,18 @@ """ from torch.utils.data import random_split -from domainlab.dsets.dset_mnist_color_solo_default import \ - DsetMNISTColorSoloDefault +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault from domainlab.dsets.utils_color_palette import default_rgb_palette # @FIXME -from domainlab.tasks.b_task import NodeTaskDict +from domainlab.tasks.b_task_classif import NodeTaskDictClassif from domainlab.tasks.utils_task import ImSize from domainlab.utils.utils_classif import mk_dummy_label_list_str -class NodeTaskMNISTColor10(NodeTaskDict): +class NodeTaskMNISTColor10(NodeTaskDictClassif): """ Use the deafult palette with 10 colors """ + @property def list_str_y(self): return mk_dummy_label_list_str("digit", 10) @@ -30,13 +30,15 @@ def get_list_domains(self): 2. better use method than property so new domains can be added """ list_domains = [] - for rgb_list in default_rgb_palette: # 10 colors + for rgb_list in default_rgb_palette: # 10 colors domain = "_".join([str(c) for c in rgb_list]) domain = "rgb_" + domain list_domains.append(domain) return list_domains - def get_dset_by_domain(self, args, na_domain, split=True): # @FIXME: different number of arguments than parent + def get_dset_by_domain( + self, args, na_domain, split=True + ): # @FIXME: different number of arguments than parent """get_dset_by_domain. :param args: :param na_domain: diff --git a/domainlab/tasks/task_pathlist.py b/domainlab/tasks/task_pathlist.py index 413dacf1f..ab00c7647 100644 --- a/domainlab/tasks/task_pathlist.py +++ b/domainlab/tasks/task_pathlist.py @@ -9,41 +9,48 @@ import torch.multiprocessing -torch.multiprocessing.set_sharing_strategy('file_system') -# "too many opened files" https://github.com/pytorch/pytorch/issues/11201 - -from torchvision import transforms - from domainlab.dsets.dset_img_path_list import DsetImPathList from domainlab.dsets.utils_data import mk_fun_label2onehot -from domainlab.tasks.b_task import NodeTaskDict +from domainlab.tasks.b_task_classif import NodeTaskDictClassif +torch.multiprocessing.set_sharing_strategy("file_system") +# "too many opened files" https://github.com/pytorch/pytorch/issues/11201 -class NodeTaskPathListDummy(NodeTaskDict): - pass +class NodeTaskPathListDummy(NodeTaskDictClassif): + """ + typedef class so that other function can use isinstance + """ -def mk_node_task_path_list(isize, - list_str_y, - trans4all, - dict_class_label2name, - dict_domain2imgroot, - dict_d2filepath_list_img, - dict_d2filepath_list_img_val, - dict_d2filepath_list_img_te, - succ=None): + def get_dset_by_domain(self, args, na_domain, split=False): + raise NotImplementedError + + +def mk_node_task_path_list( + isize, + img_trans_te, + list_str_y, + img_trans_tr, + dict_class_label_ind2name, + dict_domain2imgroot, + dict_d2filepath_list_img_tr, + dict_d2filepath_list_img_val, + dict_d2filepath_list_img_te, + succ=None, +): """mk_node_task_path_list. :param isize: :param list_str_y: - :param trans4all: - :param dict_class_label2name: + :param img_trans_tr: + :param dict_class_label_ind2name: :param dict_domain2imgroot: - :param dict_d2filepath_list_img: + :param dict_d2filepath_list_img_tr: :param dict_d2filepath_list_img_val: :param dict_d2filepath_list_img_te: :param succ: """ + class NodeTaskPathList(NodeTaskPathListDummy): """ The class TaskPathList provides the user an interface to provide a file @@ -53,22 +60,29 @@ class NodeTaskPathList(NodeTaskPathListDummy): slot contains the class label as a numerical string. e.g.: /path/2/file/art_painting/dog/pic_376.jpg 1 """ - def _get_complete_domain(self, na_domain, list_domain_path): + + def _get_complete_domain(self, na_domain, dict_domain2pathfilepath): """_get_complete_domain. :param na_domain: """ - if self._dict_domain_img_trans: - trans = self._dict_domain_img_trans[na_domain] + if na_domain not in self.list_domain_tr: + trans = img_trans_te else: - trans = trans4all + if self._dict_domain_img_trans: + trans = self._dict_domain_img_trans[na_domain] + else: + trans = img_trans_tr root_img = self.dict_domain2imgroot[na_domain] - path2filelist = list_domain_path[na_domain] + path2filelist = dict_domain2pathfilepath[na_domain] path2filelist = os.path.expanduser(path2filelist) root_img = os.path.expanduser(root_img) - dset = DsetImPathList(root_img, path2filelist, trans_img=trans, - trans_target=mk_fun_label2onehot( - len(self.list_str_y))) + dset = DsetImPathList( + root_img, + path2filelist, + trans_img=trans, + trans_target=mk_fun_label2onehot(len(self.list_str_y)), + ) return dset def get_dset_by_domain(self, args, na_domain, split=True): @@ -79,40 +93,44 @@ def get_dset_by_domain(self, args, na_domain, split=True): :param split: for test set, use the whole """ if not split: # no train/val split for test domain + # the user is required to input tr, val, te file path + # if split=False, then only te is used, which contains + # the whole dataset dset = self._get_complete_domain( - na_domain, - self._dict_domain2filepath_list_im_te) + na_domain, self._dict_domain2filepath_list_im_te + ) + # test set contains train+validation return dset, dset # @FIXME: avoid returning two identical dset = self._get_complete_domain( na_domain, - self._dict_domain2filepath_list_im) + # read training set from user configuration + self._dict_domain2filepath_list_im_tr, + ) dset_val = self._get_complete_domain( na_domain, - self._dict_domain2filepath_list_im_val) + # read validation set from user configuration + self._dict_domain2filepath_list_im_val, + ) return dset, dset_val - def conf(self, args): - """conf. - - :param args: + def conf(self): + """ + set task attribute in initialization """ self.list_str_y = list_str_y self.isize = isize + self.dict_class_label_ind2name = dict_class_label_ind2name self.dict_domain2imgroot = dict_domain2imgroot - self._dict_domain2filepath_list_im = dict_d2filepath_list_img + self._dict_domain2filepath_list_im_tr = dict_d2filepath_list_img_tr self._dict_domain2filepath_list_im_val = dict_d2filepath_list_img_val self._dict_domain2filepath_list_im_te = dict_d2filepath_list_img_te self.set_list_domains(list(self.dict_domain2imgroot.keys())) - def init_business(self, args): - """init_business. - - :param args: - """ - self.conf(args) - super().init_business(args) + def __init__(self, succ=None): + super().__init__(succ) + self.conf() return NodeTaskPathList(succ) diff --git a/domainlab/tasks/utils_task.py b/domainlab/tasks/utils_task.py index 1b840f52f..850364f0a 100644 --- a/domainlab/tasks/utils_task.py +++ b/domainlab/tasks/utils_task.py @@ -12,7 +12,7 @@ from domainlab.utils.utils_class import store_args -class ImSize(): +class ImSize: """ImSize.""" @store_args @@ -20,6 +20,7 @@ def __init__(self, i_c, i_h, i_w): """ store channel, height, width """ + @property def c(self): """image channel""" @@ -46,7 +47,7 @@ def mk_onehot(dim, ind): return vec -def mk_loader(dset, bsize, drop_last=True, shuffle=True): +def mk_loader(dset, bsize, drop_last=True, shuffle=True, num_workers=int(0)): """ :param bs: batch size """ @@ -56,10 +57,10 @@ def mk_loader(dset, bsize, drop_last=True, shuffle=True): dataset=dset, batch_size=bsize, shuffle=shuffle, - # shuffle must be true so the last incomplete - # batch get used in anohter epoch - num_workers=int(0), # @FIXME: - drop_last=drop_last) + # @FIXME: shuffle must be true so the last incomplete batch get used in another epoch? + num_workers=num_workers, # @FIXME: num_workers=int(0) can be slow? + drop_last=drop_last, + ) return loader @@ -67,6 +68,7 @@ class DsetDomainVecDecorator(Dataset): """ decorate a pytorch dataset with a fixed vector representation of domain """ + def __init__(self, dset, vec_domain, na_domain): """ :param dset: x, y @@ -104,6 +106,7 @@ class DsetDomainVecDecoratorImgPath(DsetDomainVecDecorator): returned currently not in use since it is mostly important to print predictions together with path for the test domain """ + def __getitem__(self, idx): """ :param idx: @@ -116,6 +119,7 @@ class DsetClassVecDecorator(Dataset): """ decorate a pytorch dataset with a new class name """ + def __init__(self, dset, dict_folder_name2class_global, list_str_y): """ :param dset: x, y, *d @@ -123,15 +127,19 @@ def __init__(self, dset, dict_folder_name2class_global, list_str_y): class folder of domain to glbal class """ self.dset = dset - self.class2idx = {k:v for (k,v) in self.dset.class_to_idx.items() \ - if k in self.dset.list_class_dir} + self.class2idx = { + k: v + for (k, v) in self.dset.class_to_idx.items() + if k in self.dset.list_class_dir + } assert self.class2idx self.dict_folder_name2class_global = dict_folder_name2class_global self.list_str_y = list_str_y # inverst key:value to value:key for backward map self.dict_old_idx2old_class = dict((v, k) for k, v in self.class2idx.items()) dict_class_na_local2vec_new = dict( - (k, self.fun_class_local_na2vec_new(k)) for k, v in self.class2idx.items()) + (k, self.fun_class_local_na2vec_new(k)) for k, v in self.class2idx.items() + ) self.dict_class_na_local2vec_new = dict_class_na_local2vec_new @property @@ -175,10 +183,11 @@ def __getitem__(self, idx): return tensor, vec_class_new, path[0] -class LoaderDomainLabel(): +class LoaderDomainLabel: """ wraps a dataset with domain label and into a loader """ + def __init__(self, batch_size, dim_d): """__init__. @@ -212,14 +221,12 @@ def tensor1hot2ind(tensor_label): npa_label_ind = label_ind.numpy() return npa_label_ind + # @FIXME: this function couples strongly with the task, # should be a class method of task -def img_loader2dir(loader, - folder, - test=False, - list_domain_na=None, - list_class_na=None, - batches=5): +def img_loader2dir( + loader, folder, test=False, list_domain_na=None, list_class_na=None, batches=5 +): """ save images from loader to directory so speculate if loader is correct :param loader: pytorch data loader @@ -238,7 +245,7 @@ def img_loader2dir(loader, class_label_ind_batch = tensor1hot2ind(vec_y) # get domain label - # Note 1: test loaders don't return domain labels (see NodeTaskDict.init_business) + # Note 1: test loaders don't return domain labels (see NodeTaskDictClassif.init_business) # Note 2: for train loaders domain label will be the 0th element of other_vars (see DsetDomainVecDecorator class above) has_domain_label_ind = False if not test: @@ -251,7 +258,7 @@ def img_loader2dir(loader, class_label_scalar = class_label_ind.item() if list_class_na is None: - str_class_label = "class_"+str(class_label_scalar) + str_class_label = "class_" + str(class_label_scalar) else: # @FIXME: where is the correspndance between # class ind_label and class str_label? @@ -268,12 +275,15 @@ def img_loader2dir(loader, arr = img[b_ind] img_vision = torchvision.transforms.ToPILImage()(arr) f_n = "_".join( - ["class", - str_class_label, - "domain", - str_domain_label, - "n", - str(counter)]) + [ + "class", + str_class_label, + "domain", + str_domain_label, + "n", + str(counter), + ] + ) counter += 1 path = os.path.join(folder, f_n + ".png") img_vision.save(path) diff --git a/domainlab/tasks/utils_task_dset.py b/domainlab/tasks/utils_task_dset.py index 40c63a7d7..0b3577c99 100644 --- a/domainlab/tasks/utils_task_dset.py +++ b/domainlab/tasks/utils_task_dset.py @@ -1,3 +1,8 @@ +""" +task specific dataset operation +""" +import random + from torch.utils.data import Dataset @@ -5,6 +10,7 @@ class DsetIndDecorator4XYD(Dataset): """ For dataset of x, y, d, decorate it wih index """ + def __init__(self, dset): """ :param dset: x,y,d @@ -12,7 +18,9 @@ def __init__(self, dset): tuple_m = dset[0] if len(tuple_m) < 3: raise RuntimeError( - "dataset to be wrapped should output at least x, y, and d; got length ", len(tuple_m)) + "dataset to be wrapped should output at least x, y, and d; got length ", + len(tuple_m), + ) self.dset = dset def __getitem__(self, index): @@ -24,3 +32,47 @@ def __getitem__(self, index): def __len__(self): return self.dset.__len__() + + +class DsetZip(Dataset): + """ + enable zip return in getitem: x_1, y_1, x_2, y_2 + to avoid always the same match, the second dataset does not use the same idx in __get__item() + but instead, a random one + """ + + def __init__(self, dset1, dset2, name=None): + """ + :param dset1: x1, y1, *d1 + :param dset2: x2, y2, *d2 + :param name: name of dataset + """ + self.dset1 = dset1 + self.dset2 = dset2 + self.name = name + self.len2 = self.dset2.__len__() + + def __getitem__(self, idx): + """ + :param idx: + """ + idx2 = idx + random.randrange(self.len2) + idx2 = idx2 % self.len2 + tensor_x_1, vec_y_1, vec_d_1, *others_1 = self.dset1.__getitem__(idx) + tensor_x_2, vec_y_2, vec_d_2, *others_2 = self.dset2.__getitem__(idx2) + return ( + tensor_x_1, + vec_y_1, + vec_d_1, + others_1, + tensor_x_2, + vec_y_2, + vec_d_2, + others_2, + ) + + def __len__(self): + len1 = self.dset1.__len__() + if len1 < self.len2: + return len1 + return self.len2 diff --git a/domainlab/tasks/zoo_tasks.py b/domainlab/tasks/zoo_tasks.py index 513037abd..ca050520a 100644 --- a/domainlab/tasks/zoo_tasks.py +++ b/domainlab/tasks/zoo_tasks.py @@ -1,21 +1,21 @@ -import os - -from torchvision import transforms +""" +all available tasks for domainlab +""" +from domainlab.arg_parser import mk_parser_main from domainlab.compos.pcr.request import RequestTask -from domainlab.tasks.task_folder_mk import mk_task_folder +from domainlab.tasks.task_mini_vlcs import addtask2chain from domainlab.tasks.task_mnist_color import NodeTaskMNISTColor10 -from domainlab.tasks.utils_task import ImSize +from domainlab.utils.logger import Logger from domainlab.utils.u_import import import_path -path_this_file = os.path.dirname(os.path.realpath(__file__)) - class TaskChainNodeGetter(object): """ 1. Hardcoded chain 3. Return selected node """ + def __init__(self, args): self.args = args tpath = args.tpath @@ -30,55 +30,31 @@ def __call__(self): 2. hard code seems to be the best solution """ chain = NodeTaskMNISTColor10(None) - - chain = mk_task_folder(extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", - "stuhl": "chair"}, - "sun": {"vehicle": "car", - "sofa": "chair"}, - "labelme": {"drive": "car", - "sit": "chair"} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "sun": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "labelme": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": os.path.join( - path_this_file, - "../../data/vlcs_mini/caltech/"), - "sun": os.path.join( - path_this_file, - "../../data/vlcs_mini/sun/"), - "labelme": os.path.join( - path_this_file, - "../../data/vlcs_mini/labelme/")}, - taskna="mini_vlcs", - succ=chain) + chain = addtask2chain(chain) if self.tpath is not None: node = self.task_module.get_task(self.args.task) chain.set_parent(node) chain = node if self.args.task is None: - print("") - print("overriding args.task ", - self.args.task, " to ", - node.task_name) - print("") + logger = Logger.get_logger() + logger.info("") + logger.info( + f"overriding args.task {self.args.task} " f"to {node.task_name}" + ) + logger.info("") self.request = node.task_name # @FIXME node = chain.handle(self.request) return node + + +def get_task(name=None): + """ + get build in task from DomainLab + """ + args = mk_parser_main + parser = mk_parser_main() + args = parser.parse_args("") + args.task = name + task_getter = TaskChainNodeGetter(args) + return task_getter() diff --git a/domainlab/uml/libDG.uml b/domainlab/uml/libDG.uml deleted file mode 100644 index 9b8c4e2b2..000000000 --- a/domainlab/uml/libDG.uml +++ /dev/null @@ -1,85 +0,0 @@ -@startuml -' -' *-- composition -' <|-- extension -' o-- aggregation -' -- association (1 to n or 1 to 1 or n to 1) -' ..> -'Dependency is a weaker form of bond which indicates that one class depends on -'another because it uses it at some point in time. One class depends on -'another if the independent class is a parameter variable or local variable of -'a method of the dependent class. This is different from an association, where -'an attribute of the dependent class is an instance of the independent class. -'Sometimes the relationship between two classes is very weak. They are not -'implemented with member variables at all. Rather they might be implemented as -'member function arguments. -package task { - abstract class Task { - + dim_y - } - Task <|-- TaskFolder -} - -package algos { - abstract class AlgoBuilder {} - class ConcreteAlgoBuilder {} - package trainer { - class Trainer {} - } - package observer { - class Observer {} - } - package model_selection { - class ModelSel {} - } -} - -package dataset <>{ - class Dataset { - -- - __get__item__ - -- - -- - } -} - -package model{ - abstract class Model { - + int dim_y - + int dim_d - } - abstract class ModelBuilder { - +build_part_a() - +build_part_b() - } - class ConcreteModel {} - class ConcreteModelBuilder {} -} - - -package components { - package common_networks { - } - package patterns{} - package experiment { - class Experiment {} - class TaskHandler{} - } -} - - -Experiment *-- Task -Experiment *-- Trainer -Trainer *-- Observer -Trainer *-- Model -Task o-- Dataset -Model <|-- ConcreteModel -Model *-- ModelBuilder -Experiment *-- AlgoBuilder -Experiment *-- TaskHandler -ConcreteModelBuilder -- common_networks -ConcreteAlgoBuilder -- Trainer -ConcreteAlgoBuilder -- Observer -ConcreteAlgoBuilder -- ModelSel -ConcreteModelBuilder -- ConcreteModel -@enduml diff --git a/domainlab/utils/flows_gen_img_model.py b/domainlab/utils/flows_gen_img_model.py index 0bc2d7026..0933c5bdc 100644 --- a/domainlab/utils/flows_gen_img_model.py +++ b/domainlab/utils/flows_gen_img_model.py @@ -6,7 +6,7 @@ from domainlab.utils.utils_img_sav import mk_fun_sav_img -class FlowGenImgs(): +class FlowGenImgs: def __init__(self, model, device): model = model.to(device) self.obj_recon = ReconVAEXYD(model) @@ -56,54 +56,69 @@ def gen_img_xyd(self, img, vec_y, vec_d, device, path, folder_na): def _flow_vanilla(self, img, vec_y, vec_d, device, num_sample=10): x_recon_img, str_type = self.obj_recon.recon(img) - self._save_pair(x_recon_img, device, img, str_type + '.png') + self._save_pair(x_recon_img, device, img, str_type + ".png") x_recon_img, str_type = self.obj_recon.recon(img, vec_y) - self._save_pair(x_recon_img, device, img, str_type + '.png') + self._save_pair(x_recon_img, device, img, str_type + ".png") if vec_d is not None: x_recon_img, str_type = self.obj_recon.recon(img, None, vec_d) - self._save_pair(x_recon_img, device, img, str_type + '.png') + self._save_pair(x_recon_img, device, img, str_type + ".png") for i in range(num_sample): x_recon_img, str_type = self.obj_recon.recon(img, vec_y, vec_d, True, True) x_recon_img = x_recon_img.to(device) comparison = torch.cat([img, x_recon_img]) - self.sav_fun(comparison, str_type + str(i) + '.png') + self.sav_fun(comparison, str_type + str(i) + ".png") def _flow_cf_y(self, img, vec_y, vec_d, device): """ scan possible values of vec_y """ - recon_list, str_type = self.obj_recon.recon_cf(img, "y", vec_y.shape[1], device, - zx2fill=None) - self._save_list(recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png") - recon_list, str_type = self.obj_recon.recon_cf(img, "y", vec_y.shape[1], device, zx2fill=0) - self._save_list(recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png") + recon_list, str_type = self.obj_recon.recon_cf( + img, "y", vec_y.shape[1], device, zx2fill=None + ) + self._save_list( + recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png" + ) + recon_list, str_type = self.obj_recon.recon_cf( + img, "y", vec_y.shape[1], device, zx2fill=0 + ) + self._save_list( + recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png" + ) if vec_d is not None: recon_list, str_type = self.obj_recon.recon_cf( - img, "y", vec_y.shape[1], device, - vec_d=vec_d, - zx2fill=0) - self._save_list(recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png") + img, "y", vec_y.shape[1], device, vec_d=vec_d, zx2fill=0 + ) + self._save_list( + recon_list, device, img, "_".join(["recon_cf_y", str_type]) + ".png" + ) def _flow_cf_d(self, img, vec_y, vec_d, device): """ scan possible values of vec_y """ - recon_list, str_type = self.obj_recon.recon_cf(img, "d", vec_d.shape[1], device, - zx2fill=None) - self._save_list(recon_list, device, img, "_".join(["recon_cf_d", str_type]) +".png") - recon_list, str_type = self.obj_recon.recon_cf(img, "d", vec_d.shape[1], device, zx2fill=0) - self._save_list(recon_list, device, img, "_".join(["recon_cf_d", str_type]) +".png") + recon_list, str_type = self.obj_recon.recon_cf( + img, "d", vec_d.shape[1], device, zx2fill=None + ) + self._save_list( + recon_list, device, img, "_".join(["recon_cf_d", str_type]) + ".png" + ) + recon_list, str_type = self.obj_recon.recon_cf( + img, "d", vec_d.shape[1], device, zx2fill=0 + ) + self._save_list( + recon_list, device, img, "_".join(["recon_cf_d", str_type]) + ".png" + ) def fun_gen(model, device, node, args, subfolder_na, output_folder_na="gen"): flow = FlowGenImgs(model, device) - path = os.path.join(args.out, output_folder_na, node.task_name, args.aname, subfolder_na) - flow.gen_img_loader(node.loader_te, device, - path=path, - domain="_".join(args.te_d)) - flow.gen_img_loader(node.loader_tr, device, - path=path, - domain="_".join(node.list_domain_tr)) + path = os.path.join( + args.out, output_folder_na, node.task_name, args.model, subfolder_na + ) + flow.gen_img_loader(node.loader_te, device, path=path, domain="_".join(args.te_d)) + flow.gen_img_loader( + node.loader_tr, device, path=path, domain="_".join(node.list_domain_tr) + ) diff --git a/domainlab/utils/generate_benchmark_plots.py b/domainlab/utils/generate_benchmark_plots.py index 7f49bbb30..e8196d8e3 100644 --- a/domainlab/utils/generate_benchmark_plots.py +++ b/domainlab/utils/generate_benchmark_plots.py @@ -1,22 +1,33 @@ -''' +""" generate the benchmark plots by calling the gen_bencmark_plots(...) function -''' +""" import os -from ast import literal_eval # literal_eval can safe evaluate python expression -import matplotlib.pyplot as plt +from ast import literal_eval # literal_eval can safe evaluate python expression + import matplotlib +import matplotlib.pyplot as plt +import numpy as np import pandas as pd import seaborn as sns -import numpy as np -matplotlib.use('Agg') +from domainlab.utils.logger import Logger + +matplotlib.use("Agg") -COLNAME_ALGO = "algo" +# header of the csv file: +# param_index, task, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc + +COLNAME_METHOD = "method" +COLNAME_IDX_PARAM = "param_index" COLNAME_PARAM = "params" +G_DF_TASK_COL = 1 # column in which the method name is saved +G_DF_PLOT_COL_METRIC_START = 9 # first 0-6 columns are not metric -def gen_benchmark_plots(agg_results: str, output_dir: str): - ''' +def gen_benchmark_plots( + agg_results: str, output_dir: str, use_param_index: bool = True +): + """ generate the benchmark plots from a csv file containing the aggregated restults. The csv file must have the columns: [param_index, task, algo, epos, te_d, seed, params, ...] @@ -25,146 +36,253 @@ def gen_benchmark_plots(agg_results: str, output_dir: str): agg_results: path to the csv file output_dir: path to a folder which shall contain the results - ''' - raw_df = pd.read_csv(agg_results, index_col=False, - converters={COLNAME_PARAM: literal_eval}, - # literal_eval can safe evaluate python expression - skipinitialspace=True) - raw_df[COLNAME_PARAM] = round_vals_in_dict(raw_df[COLNAME_PARAM]) - # crop param_index and task from the dataframe - dataframe = raw_df.iloc[:, 2:] # @FIXME: hard coded + skip_gen: Skips the actual plotting, used to speed up testing. + """ + raw_df = pd.read_csv( + agg_results, + index_col=False, + converters={COLNAME_PARAM: literal_eval}, + # literal_eval can safe evaluate python expression + skipinitialspace=True, + ) + + raw_df[COLNAME_PARAM] = round_vals_in_dict( + raw_df[[COLNAME_IDX_PARAM, COLNAME_PARAM]], use_param_index + ) + # generating plot - gen_plots(dataframe, output_dir) + gen_plots(raw_df, output_dir, use_param_index) -def round_vals_in_dict(df_column_in): - ''' +def round_vals_in_dict(df_column_in, use_param_index): + """ replaces the dictionary by a string containing only the significant digits of the hyperparams - df_column_in: columns of the dataframe containing the dictionary of hyperparams - ''' + or (if use_param_index = True) by the parameter index + df_column_in: columns of the dataframe containing the param index and the dictionary of + hyperparams in the form [param_index, params] + use_param_index: usage of param_index instead of exact values + """ df_column = df_column_in.copy() - df_column_out = df_column_in.copy() + df_column_out = df_column_in[COLNAME_IDX_PARAM].copy() + df_column_out = df_column_out.astype(str) for i in range(df_column.shape[0]): - string = '' - for num, val in enumerate(list(df_column[i].values())): - key = list(df_column[i].keys())[num] - val = np.format_float_scientific(val, precision=1, unique=False, trim='0') - string += str(key) + ': ' + str(val) + ', ' - df_column_out[i] = string[:-2] + if not use_param_index: + string = "" + for num, val in enumerate(list(df_column[COLNAME_PARAM][i].values())): + key = list(df_column[COLNAME_PARAM][i].keys())[num] + val = np.format_float_scientific( + val, precision=1, unique=False, trim="0" + ) + string += str(key) + ": " + str(val) + ", " + df_column_out[i] = string[:-2] # remove ', ' from the end of the string + else: + string = "idx: " + str(df_column[COLNAME_IDX_PARAM][i]) + df_column_out[i] = string return df_column_out -def gen_plots(dataframe: pd.DataFrame, output_dir: str): - ''' +def gen_plots(dataframe: pd.DataFrame, output_dir: str, use_param_index: bool): + """ dataframe: dataframe with columns - [' algo', ' epos', ' te_d', ' seed', ' params', ' acc', ' precision', ... ] - ''' + ['param_index','task',' algo',' epos',' te_d',' seed',' params',' acc','precision',...] + """ os.makedirs(output_dir, exist_ok=True) + obj = dataframe.columns[G_DF_PLOT_COL_METRIC_START:] + + # boxplots + for objective in obj: + boxplot( + dataframe, objective, file=output_dir + "/variational_plots/" + objective + ) + # scatterplot matrices - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix_reg.png', - reg=True, distinguish_param_setups=False) - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix.png', - reg=False, distinguish_param_setups=False) - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix_dist_reg.png', - reg=True, distinguish_param_setups=True) - scatterplot_matrix(dataframe, file=output_dir + '/sp_matrix_dist.png', - reg=False, distinguish_param_setups=True) + scatterplot_matrix( + dataframe, + use_param_index, + file=output_dir + "/sp_matrix_reg.png", + kind="reg", + distinguish_param_setups=False, + ) + scatterplot_matrix( + dataframe, + use_param_index, + file=output_dir + "/sp_matrix.png", + kind="scatter", + distinguish_param_setups=False, + ) + scatterplot_matrix( + dataframe, + use_param_index, + file=output_dir + "/sp_matrix_dist_reg.png", + kind="reg", + distinguish_param_setups=True, + ) + scatterplot_matrix( + dataframe, + use_param_index, + file=output_dir + "/sp_matrix_dist.png", + kind="scatter", + distinguish_param_setups=True, + ) # radar plots - radar_plot(dataframe, file=output_dir + '/radar_dist.png', distinguish_hyperparam=True) - radar_plot(dataframe, file=output_dir + '/radar.png', distinguish_hyperparam=False) + radar_plot( + dataframe, file=output_dir + "/radar_dist.png", distinguish_hyperparam=True + ) + radar_plot(dataframe, file=output_dir + "/radar.png", distinguish_hyperparam=False) # scatter plots for parirs of objectives - os.makedirs(output_dir + '/scatterpl', exist_ok=True) - obj = dataframe.columns[5:] + os.makedirs(output_dir + "/scatterpl", exist_ok=True) for i, obj_i in enumerate(obj): - for j in range(i+1, len(obj)): + for j in range(i + 1, len(obj)): try: - scatterplot(dataframe, [obj_i, obj[j]], - file=output_dir + '/scatterpl/' + obj_i + '_' + obj[j] + '.png') + scatterplot( + dataframe, + [obj_i, obj[j]], + file=output_dir + "/scatterpl/" + obj_i + "_" + obj[j] + ".png", + ) except IndexError: - print(f'WARNING: disabling kde because cov matrix is singular for objectives ' - f'{obj_i} & {obj[j]}') - scatterplot(dataframe, [obj_i, obj[j]], - file=output_dir + '/scatterpl/' + obj_i + '_' + obj[j] + '.png', - kde=False) + logger = Logger.get_logger() + logger.warning( + f"disabling kde because cov matrix is singular for objectives " + f"{obj_i} & {obj[j]}" + ) + scatterplot( + dataframe, + [obj_i, obj[j]], + file=output_dir + "/scatterpl/" + obj_i + "_" + obj[j] + ".png", + kde=False, + ) # create plots for the different algortihms - for algorithm in dataframe[COLNAME_ALGO].unique(): - os.makedirs(output_dir + '/' + str(algorithm), exist_ok=True) - dataframe_algo = dataframe[dataframe[COLNAME_ALGO] == algorithm] + for algorithm in dataframe[COLNAME_METHOD].unique(): + os.makedirs(output_dir + "/" + str(algorithm), exist_ok=True) + dataframe_algo = dataframe[dataframe[COLNAME_METHOD] == algorithm] + + # boxplots + for objective in obj: + boxplot( + dataframe_algo, + objective, + file=output_dir + + "/" + + str(algorithm) + + "/variational_plots/" + + objective, + ) # scatterplot matrices - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix_reg.png', - reg=True, distinguish_param_setups=False) - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix.png', - reg=False, distinguish_param_setups=False) - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix_dist_reg.png', - reg=True, distinguish_param_setups=True) - scatterplot_matrix(dataframe_algo, - file=output_dir + '/' + str(algorithm) + '/sp_matrix_dist.png', - reg=False, distinguish_param_setups=True) + scatterplot_matrix( + dataframe_algo, + use_param_index, + file=output_dir + "/" + str(algorithm) + "/sp_matrix_reg.png", + kind="reg", + distinguish_param_setups=False, + ) + scatterplot_matrix( + dataframe_algo, + use_param_index, + file=output_dir + "/" + str(algorithm) + "/sp_matrix.png", + kind="scatter", + distinguish_param_setups=False, + ) + scatterplot_matrix( + dataframe_algo, + use_param_index, + file=output_dir + "/" + str(algorithm) + "/sp_matrix_dist_reg.png", + kind="reg", + distinguish_param_setups=True, + ) + scatterplot_matrix( + dataframe_algo, + use_param_index, + file=output_dir + "/" + str(algorithm) + "/sp_matrix_dist.png", + kind="scatter", + distinguish_param_setups=True, + ) # radar plots - radar_plot(dataframe_algo, file=output_dir + '/' + str(algorithm) + '/radar_dist.png', - distinguish_hyperparam=True) - radar_plot(dataframe_algo, file=output_dir + '/' + str(algorithm) + '/radar.png', - distinguish_hyperparam=False) + radar_plot( + dataframe_algo, + file=output_dir + "/" + str(algorithm) + "/radar_dist.png", + distinguish_hyperparam=True, + ) + radar_plot( + dataframe_algo, + file=output_dir + "/" + str(algorithm) + "/radar.png", + distinguish_hyperparam=False, + ) # scatter plots for parirs of objectives - os.makedirs(output_dir + '/' + str(algorithm) + '/scatterpl', exist_ok=True) - obj = dataframe_algo.columns[5:] + os.makedirs(output_dir + "/" + str(algorithm) + "/scatterpl", exist_ok=True) for i, obj_i in enumerate(obj): for j in range(i + 1, len(obj)): try: - scatterplot(dataframe_algo, [obj_i, obj[j]], - file=output_dir + '/' + str(algorithm) + - '/scatterpl/' + obj_i + '_' + obj[j] + '.png', - distinguish_hyperparam=True) + scatterplot( + dataframe_algo, + [obj_i, obj[j]], + file=output_dir + + "/" + + str(algorithm) + + "/scatterpl/" + + obj_i + + "_" + + obj[j] + + ".png", + distinguish_hyperparam=True, + ) except IndexError: - print(f'WARNING: disabling kde because cov matrix is singular for objectives ' - f'{obj_i} & {obj[j]}') - scatterplot(dataframe_algo, [obj_i, obj[j]], - file=output_dir + '/' + str(algorithm) + - '/scatterpl/' + obj_i + '_' + obj[j] + '.png', - kde=False, - distinguish_hyperparam=True) - - -def scatterplot_matrix(dataframe_in, file=None, reg=True, distinguish_param_setups=True): - ''' + logger = Logger.get_logger() + logger.warning( + f"WARNING: disabling kde because cov matrix is singular " + f"for objectives {obj_i} & {obj[j]}" + ) + scatterplot( + dataframe_algo, + [obj_i, obj[j]], + file=output_dir + + "/" + + str(algorithm) + + "/scatterpl/" + + obj_i + + "_" + + obj[j] + + ".png", + kde=False, + distinguish_hyperparam=True, + ) + + +def scatterplot_matrix( + dataframe_in, use_param_index, file=None, kind="reg", distinguish_param_setups=True +): + """ dataframe: dataframe containing the data with columns [algo, epos, te_d, seed, params, obj1, ..., obj2] file: filename to save the plots (if None, the plot will not be saved) reg: if True a regression line will be plotted over the data distinguish_param_setups: if True the plot will not only distinguish between models, but also between the parameter setups - ''' + """ dataframe = dataframe_in.copy() - index = list(range(5, dataframe.shape[1])) + index = list(range(G_DF_PLOT_COL_METRIC_START, dataframe.shape[1])) if distinguish_param_setups: dataframe_ = dataframe.iloc[:, index] - dataframe_.insert(0, 'label', - dataframe[COLNAME_ALGO].astype(str) + ', ' + - dataframe[COLNAME_PARAM].astype(str)) + dataframe_.insert( + 0, + "label", + dataframe[COLNAME_METHOD].astype(str) + + ", " + + dataframe[COLNAME_PARAM].astype(str), + ) + + g_p = sns.pairplot(data=dataframe_, hue="label", corner=True, kind=kind) else: - index_ = list(range(5, dataframe.shape[1])) - index_.insert(0, 0) + index_ = list(range(G_DF_PLOT_COL_METRIC_START, dataframe.shape[1])) + index_.insert(0, G_DF_TASK_COL) dataframe_ = dataframe.iloc[:, index_] - if reg: - if not distinguish_param_setups: - g_p = sns.pairplot(data=dataframe_, hue=COLNAME_ALGO, corner=True, kind='reg') - else: - g_p = sns.pairplot(data=dataframe_, hue='label', corner=True, kind='reg') - else: - if not distinguish_param_setups: - g_p = sns.pairplot(data=dataframe_, hue=COLNAME_ALGO, corner=True) - else: - g_p = sns.pairplot(data=dataframe_, hue='label', corner=True) + g_p = sns.pairplot(data=dataframe_, hue=COLNAME_METHOD, corner=True, kind=kind) for i in range(len(index)): for j in range(len(index)): @@ -174,7 +292,10 @@ def scatterplot_matrix(dataframe_in, file=None, reg=True, distinguish_param_setu g_p.axes[j, k].set_ylim((-0.1, 1.1)) g_p.fig.set_size_inches(12.5, 12) - sns.move_legend(g_p, loc='upper right', bbox_to_anchor=(1., 1.), ncol=1) + if use_param_index and distinguish_param_setups: + sns.move_legend(g_p, loc="upper right", bbox_to_anchor=(1.0, 1.0), ncol=3) + else: + sns.move_legend(g_p, loc="upper right", bbox_to_anchor=(1.0, 1.0), ncol=1) plt.tight_layout() if file is not None: @@ -182,7 +303,7 @@ def scatterplot_matrix(dataframe_in, file=None, reg=True, distinguish_param_setu def scatterplot(dataframe_in, obj, file=None, kde=True, distinguish_hyperparam=False): - ''' + """ dataframe: dataframe containing the data with columns [algo, epos, te_d, seed, params, obj1, ..., obj2] obj1 & obj2: name of the objectives which shall be plotted against each other @@ -190,7 +311,7 @@ def scatterplot(dataframe_in, obj, file=None, kde=True, distinguish_hyperparam=F kde: if True the distribution of the points will be estimated and plotted as kde plot distinguish_param_setups: if True the plot will not only distinguish between models, but also between the parameter setups - ''' + """ obj1, obj2 = obj dataframe = dataframe_in.copy() @@ -198,69 +319,127 @@ def scatterplot(dataframe_in, obj, file=None, kde=True, distinguish_hyperparam=F if distinguish_hyperparam: if kde: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1), kind='kde', - zorder=0, levels=8, alpha=0.35, warn_singular=False) - gg_p = sns.scatterplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, - ax=g_p.ax_joint) + g_p = sns.jointplot( + data=dataframe, + x=obj1, + y=obj2, + hue=COLNAME_PARAM, + xlim=(-0.1, 1.1), + ylim=(-0.1, 1.1), + kind="kde", + zorder=0, + levels=8, + alpha=0.35, + warn_singular=False, + ) + gg_p = sns.scatterplot( + data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, ax=g_p.ax_joint + ) else: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_PARAM, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1)) + g_p = sns.jointplot( + data=dataframe, + x=obj1, + y=obj2, + hue=COLNAME_PARAM, + xlim=(-0.1, 1.1), + ylim=(-0.1, 1.1), + ) gg_p = g_p.ax_joint else: if kde: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_ALGO, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1), kind='kde', - zorder=0, levels=8, alpha=0.35, warn_singular=False) - gg_p = sns.scatterplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_ALGO, - style=COLNAME_PARAM, - ax=g_p.ax_joint) + g_p = sns.jointplot( + data=dataframe, + x=obj1, + y=obj2, + hue=COLNAME_METHOD, + xlim=(-0.1, 1.1), + ylim=(-0.1, 1.1), + kind="kde", + zorder=0, + levels=8, + alpha=0.35, + warn_singular=False, + ) + gg_p = sns.scatterplot( + data=dataframe, + x=obj1, + y=obj2, + hue=COLNAME_METHOD, + style=COLNAME_PARAM, + ax=g_p.ax_joint, + ) else: - g_p = sns.jointplot(data=dataframe, x=obj1, y=obj2, hue=COLNAME_ALGO, - xlim=(-0.1, 1.1), ylim=(-0.1, 1.1)) - gg_p = sns.scatterplot(data=dataframe, x=obj1, y=obj2, style=COLNAME_PARAM, - ax=g_p.ax_joint) - - gg_p.set_aspect('equal') - gg_p.legend(fontsize=6, loc='best') + g_p = sns.jointplot( + data=dataframe, + x=obj1, + y=obj2, + hue=COLNAME_METHOD, + xlim=(-0.1, 1.1), + ylim=(-0.1, 1.1), + ) + gg_p = sns.scatterplot( + data=dataframe, x=obj1, y=obj2, style=COLNAME_PARAM, ax=g_p.ax_joint + ) + + gg_p.set_aspect("equal") + gg_p.legend(fontsize=6, loc="best") if file is not None: plt.savefig(file, dpi=300) def max_0_x(x_arg): - ''' + """ max(0, x_arg) - ''' + """ return max(0, x_arg) def radar_plot(dataframe_in, file=None, distinguish_hyperparam=True): - ''' + """ dataframe_in: dataframe containing the data with columns [algo, epos, te_d, seed, params, obj1, ..., obj2] file: filename to save the plots (if None, the plot will not be saved) distinguish_param_setups: if True the plot will not only distinguish between models, but also between the parameter setups - ''' + """ dataframe = dataframe_in.copy() if distinguish_hyperparam: - dataframe.insert(0, 'label', - dataframe[COLNAME_ALGO].astype(str) + ', ' + - dataframe[COLNAME_PARAM].astype(str)) + dataframe.insert( + 0, + "label", + dataframe[COLNAME_METHOD].astype(str) + + ", " + + dataframe[COLNAME_PARAM].astype(str), + ) else: - dataframe.insert(0, 'label', dataframe[COLNAME_ALGO]) - index = list(range(6, dataframe.shape[1])) - num_lines = len(dataframe['label'].unique()) - _, axis = plt.subplots(figsize=(9, 9 + (0.28 * num_lines)), subplot_kw=dict(polar=True)) + dataframe.insert(0, "label", dataframe[COLNAME_METHOD]) + # we need "G_DF_PLOT_COL_METRIC_START + 1" as we did insert the columns 'label' at index 0 + index = list(range(G_DF_PLOT_COL_METRIC_START + 1, dataframe.shape[1])) + num_lines = len(dataframe["label"].unique()) + _, axis = plt.subplots( + figsize=(9, 9 + (0.28 * num_lines)), subplot_kw=dict(polar=True) + ) num = 0 # Split the circle into even parts and save the angles # so we know where to put each axis. - angles = list(np.linspace(0, 2 * np.pi, len(dataframe.columns[index]), endpoint=False)) - for algo_name in dataframe['label'].unique(): - mean = dataframe.loc[dataframe['label'] == algo_name].iloc[:, index].mean().to_list() - std = dataframe.loc[dataframe['label'] == algo_name].iloc[:, index].std().to_list() + angles = list( + np.linspace(0, 2 * np.pi, len(dataframe.columns[index]), endpoint=False) + ) + for algo_name in dataframe["label"].unique(): + mean = ( + dataframe.loc[dataframe["label"] == algo_name] + .iloc[:, index] + .mean() + .to_list() + ) + std = ( + dataframe.loc[dataframe["label"] == algo_name] + .iloc[:, index] + .std() + .to_list() + ) angles_ = angles # The plot is a circle, so we need to "complete the loop" @@ -270,15 +449,22 @@ def radar_plot(dataframe_in, file=None, distinguish_hyperparam=True): angles_ = np.array(angles_ + angles_[:1]) # Draw the outline of the data. - axis.plot(angles_, mean, - color=list(plt.rcParams["axes.prop_cycle"])[num]['color'], - linewidth=2, label=algo_name) + axis.plot( + angles_, + mean, + color=list(plt.rcParams["axes.prop_cycle"])[num]["color"], + linewidth=2, + label=algo_name, + ) # Fill it in. - axis.fill_between(angles_, list(map(max_0_x, mean - std)), - y2=mean + std, - color=list(plt.rcParams["axes.prop_cycle"])[num]['color'], - alpha=0.1) + axis.fill_between( + angles_, + list(map(max_0_x, mean - std)), + y2=mean + std, + color=list(plt.rcParams["axes.prop_cycle"])[num]["color"], + alpha=0.1, + ) num += 1 num = num % len(list(plt.rcParams["axes.prop_cycle"])) @@ -291,8 +477,180 @@ def radar_plot(dataframe_in, file=None, distinguish_hyperparam=True): axis.set_ylim((0, 1)) - plt.legend(loc='lower right', bbox_to_anchor=(1., 1.035), - ncol=1, fontsize=10) + plt.legend(loc="lower right", bbox_to_anchor=(1.0, 1.035), ncol=1, fontsize=10) if file is not None: plt.savefig(file, dpi=300) + + +def boxplot(dataframe_in, obj, file=None): + """ + generate the boxplots + dataframe_in: dataframe containing the data with columns + [param_idx, task , algo, epos, te_d, seed, params, obj1, ..., obj2] + obj: objective to be considered in the plot (needs to be contained in dataframe_in) + file: foldername to save the plots (if None, the plot will not be saved) + """ + boxplot_stochastic(dataframe_in, obj, file=file) + boxplot_systematic(dataframe_in, obj, file=file) + + +def boxplot_stochastic(dataframe_in, obj, file=None): + """ + generate boxplot for stochastic variation + dataframe_in: dataframe containing the data with columns + [param_idx, task , algo, epos, te_d, seed, params, obj1, ..., obj2] + obj: objective to be considered in the plot (needs to be contained in dataframe_in) + file: foldername to save the plots (if None, the plot will not be saved) + """ + dataframe = dataframe_in.copy() + os.makedirs(file, exist_ok=True) + + ### stochastic variation + _, axes = plt.subplots( + 1, + len(dataframe[COLNAME_METHOD].unique()), + sharey=True, + figsize=(3 * len(dataframe[COLNAME_METHOD].unique()), 6), + ) + # iterate over all algorithms + for num, algo in enumerate(list(dataframe[COLNAME_METHOD].unique())): + # distinguish if the algorithm does only have one param setup or multiple + if len(dataframe[COLNAME_METHOD].unique()) > 1: + # generate boxplot and swarmplot + sns.boxplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_IDX_PARAM, + y=obj, + ax=axes[num], + showfliers=False, + boxprops={"facecolor": (0.4, 0.6, 0.8, 0.5)}, + ) + sns.swarmplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_IDX_PARAM, + y=obj, + legend=False, + ax=axes[num], + ) + # remove legend, set ylim, set x-label and remove y-label + axes[num].legend([], [], frameon=False) + axes[num].set_ylim([-0.1, 1.1]) + axes[num].set_xlabel(algo) + if num != 0: + axes[num].set_ylabel("") + else: + sns.boxplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_IDX_PARAM, + y=obj, + ax=axes, + showfliers=False, + boxprops={"facecolor": (0.4, 0.6, 0.8, 0.5)}, + ) + sns.swarmplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_IDX_PARAM, + y=obj, + hue=COLNAME_IDX_PARAM, + legend=False, + ax=axes, + palette=sns.cubehelix_palette( + n_colors=len( + dataframe[dataframe[COLNAME_METHOD] == algo][ + COLNAME_IDX_PARAM + ].unique() + ) + ), + ) + axes.legend([], [], frameon=False) + axes.set_ylim([-0.1, 1.1]) + axes.set_xlabel(algo) + plt.tight_layout() + if file is not None: + plt.savefig(file + "/stochastic_variation.png", dpi=300) + + +def boxplot_systematic(dataframe_in, obj, file=None): + """ + generate boxplot for ssystemtic variation + dataframe_in: dataframe containing the data with columns + [param_idx, task , algo, epos, te_d, seed, params, obj1, ..., obj2] + obj: objective to be considered in the plot (needs to be contained in dataframe_in) + file: foldername to save the plots (if None, the plot will not be saved) + """ + dataframe = dataframe_in.copy() + os.makedirs(file, exist_ok=True) + + ### systematic variation + _, axes = plt.subplots( + 1, + len(dataframe[COLNAME_METHOD].unique()), + sharey=True, + figsize=(3 * len(dataframe[COLNAME_METHOD].unique()), 6), + ) + + for num, algo in enumerate(list(dataframe[COLNAME_METHOD].unique())): + # distinguish if the algorithm does only have one param setup or multiple + if len(dataframe[COLNAME_METHOD].unique()) > 1: + # generate boxplot and swarmplot + sns.boxplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_METHOD, + y=obj, + ax=axes[num], + showfliers=False, + boxprops={"facecolor": (0.4, 0.6, 0.8, 0.5)}, + ) + sns.swarmplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_METHOD, + y=obj, + hue=COLNAME_IDX_PARAM, + legend=False, + ax=axes[num], + palette=sns.cubehelix_palette( + n_colors=len( + dataframe[dataframe[COLNAME_METHOD] == algo][ + COLNAME_IDX_PARAM + ].unique() + ) + ), + ) + # remove legend, set ylim, set x-label and remove y-label + axes[num].legend([], [], frameon=False) + axes[num].set_ylim([-0.1, 1.1]) + axes[num].set_xlabel(" ") + if num != 0: + axes[num].set_ylabel("") + else: + sns.boxplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_METHOD, + y=obj, + ax=axes, + showfliers=False, + boxprops={"facecolor": (0.4, 0.6, 0.8, 0.5)}, + ) + sns.swarmplot( + data=dataframe[dataframe[COLNAME_METHOD] == algo], + x=COLNAME_METHOD, + y=obj, + hue=COLNAME_IDX_PARAM, + legend=False, + ax=axes, + palette=sns.cubehelix_palette( + n_colors=len( + dataframe[dataframe[COLNAME_METHOD] == algo][ + COLNAME_IDX_PARAM + ].unique() + ) + ), + ) + axes.legend([], [], frameon=False) + axes.set_ylim([-0.1, 1.1]) + axes.set_xlabel(" ") + plt.tight_layout() + + if file is not None: + plt.savefig(file + "/systematic_variation.png", dpi=300) diff --git a/domainlab/utils/get_git_tag.py b/domainlab/utils/get_git_tag.py index e9942b06e..977dda1f2 100644 --- a/domainlab/utils/get_git_tag.py +++ b/domainlab/utils/get_git_tag.py @@ -2,32 +2,38 @@ import warnings from subprocess import CalledProcessError +from domainlab.utils.logger import Logger + def get_git_tag(print_diff=False): flag_not_commited = False + logger = Logger.get_logger() try: - subprocess.check_output( - ['git', 'diff-index', '--quiet', 'HEAD']) + subprocess.check_output(["git", "diff-index", "--quiet", "HEAD"]) except CalledProcessError: - print("\n\n") + logger.warning("\n\n") + logger.warning("!!!: not committed yet") warnings.warn("!!!: not committed yet") flag_not_commited = True - print("\n\n") + logger.warning("\n\n") try: - diff_byte = subprocess.check_output(['git', 'diff']) + diff_byte = subprocess.check_output(["git", "diff"]) if print_diff: - print(diff_byte) # print is currently ugly, do not use! + logger.info(str(diff_byte)) # print is currently ugly, do not use! except Exception: + logger = Logger.get_logger() + logger.warning("not in a git repository") warnings.warn("not in a git repository") try: - tag_byte = subprocess.check_output( - ["git", "describe", "--always"]).strip() - print(tag_byte) + tag_byte = subprocess.check_output(["git", "describe", "--always"]).strip() + logger.info(str(tag_byte)) tag_str = str(tag_byte) git_str = tag_str.replace("'", "") if flag_not_commited: git_str = git_str + "_not_commited" return git_str except Exception: + logger = Logger.get_logger() + logger.warning("not in a git repository") warnings.warn("not in a git repository") return "no_git_version" diff --git a/domainlab/utils/hyperparameter_gridsearch.py b/domainlab/utils/hyperparameter_gridsearch.py new file mode 100644 index 000000000..6ac878c4a --- /dev/null +++ b/domainlab/utils/hyperparameter_gridsearch.py @@ -0,0 +1,436 @@ +""" +gridsearch for the hyperparameter space + +def add_next_param_from_list is an recursive function to make cartesian product along all the scalar hyper-parameters, this resursive function is used +in def grid_task + +""" +import copy +import json +import os +import warnings + +import numpy as np +import pandas as pd + +import domainlab.utils.hyperparameter_sampling as sampling +from domainlab import g_name_num_shared_param_samples_rand_search +from domainlab.utils.get_git_tag import get_git_tag +from domainlab.utils.logger import Logger + +G_MODEL_NA = "model" +G_METHOD_NA = "method" + + +def round_to_discreate_grid_uniform(grid, param_config): + """ + round the values of the grid to the grid spacing specified in the config + for uniform and loguniform grids + """ + if float(param_config["step"]) == 0: + return grid + mini = float(param_config["min"]) + maxi = float(param_config["max"]) + if maxi - mini < float(param_config["step"]): + raise RuntimeError( + "distance between max and min to small for defined step size" + ) + + discreate_gird = np.arange( + mini, maxi + float(param_config["step"]), step=float(param_config["step"]) + ) + for num, elem in enumerate(list(grid)): + # search for the closest allowed grid point to the scalar elem + grid[num] = discreate_gird[(np.abs(discreate_gird - elem)).argmin()] + grid_unique = np.unique(grid) + grid_out = grid_unique + return grid_out + + +def round_to_discreate_grid_normal(grid, param_config): + """ + round the values of the grid to the grid spacing specified in the config + for normal and lognormal grids + """ + if float(param_config["step"]) == 0: + return grid + # for normal and lognormal no min and max is provided + # in this case the grid is constructed around the mean + neg_steps = np.ceil( + (float(param_config["mean"]) - np.min(grid)) / float(param_config["step"]) + ) + pos_steps = np.ceil( + (np.max(grid) - float(param_config["mean"])) / float(param_config["step"]) + ) + mini = float(param_config["mean"]) - float(param_config["step"]) * neg_steps + maxi = float(param_config["mean"]) + float(param_config["step"]) * pos_steps + + discreate_gird = np.arange(mini, maxi, step=float(param_config["step"])) + for num, elem in enumerate(list(grid)): + grid[num] = discreate_gird[(np.abs(discreate_gird - elem)).argmin()] + return np.unique(grid) + + +def uniform_grid(param_config): + """ + get a uniform distributed grid given the specifications in the param_config + param_config: config which needs to contain 'num', 'max', 'min', 'step' + """ + num = int(param_config["num"]) + maxi = float(param_config["max"]) + mini = float(param_config["min"]) + step = (maxi - mini) / num + # linspace does include the end of the interval and include the beginning + # we move away from mini and maxi to sample inside the open interval (mini, maxi) + grid = np.linspace(mini + step / 2, maxi - step / 2, num) + if "step" in param_config.keys(): + return round_to_discreate_grid_uniform(grid, param_config) + return grid + + +def loguniform_grid(param_config): + """ + get a loguniform distributed grid given the specifications in the param_config + param_config: config which needs to contain 'num', 'max', 'min' + """ + num = int(param_config["num"]) + maxi = np.log10(float(param_config["max"])) + mini = np.log10(float(param_config["min"])) + step = (maxi - mini) / num + # linspace does exclude the end of the interval and include the beginning + grid = 10 ** np.linspace(mini + step / 2, maxi - step / 2, num) + if "step" in param_config.keys(): + return round_to_discreate_grid_uniform(grid, param_config) + return grid + + +def normal_grid(param_config, lognormal=False): + """ + get a normal distributed grid given the specifications in the param_config + param_config: config which needs to contain 'num', 'mean', 'std' + """ + if int(param_config["num"]) == 1: + return np.array([float(param_config["mean"])]) + # Box–Muller transform to get from a uniform distribution to a normal distribution + num = int(np.floor(int(param_config["num"]) / 2)) + step = 2 / (int(param_config["num"]) + 1) + # for a even number of samples + if int(param_config["num"]) % 2 == 0: + param_grid = np.arange(step, 1, step=step)[:num] + stnormal_grid = np.sqrt(-2 * np.log(param_grid)) + stnormal_grid = np.append(stnormal_grid, -stnormal_grid) + stnormal_grid = stnormal_grid / np.std(stnormal_grid) + stnormal_grid = float(param_config["std"]) * stnormal_grid + float( + param_config["mean"] + ) + # for a odd number of samples + else: + param_grid = np.arange(step, 1, step=step)[:num] + stnormal_grid = np.sqrt(-2 * np.log(param_grid)) + stnormal_grid = np.append(stnormal_grid, -stnormal_grid) + stnormal_grid = np.append(stnormal_grid, 0) + stnormal_grid = stnormal_grid / np.std(stnormal_grid) + stnormal_grid = float(param_config["std"]) * stnormal_grid + float( + param_config["mean"] + ) + + if "step" in param_config.keys() and lognormal is False: + return round_to_discreate_grid_normal(stnormal_grid, param_config) + return stnormal_grid + + +def lognormal_grid(param_config): + """ + get a normal distributed grid given the specifications in the param_config + param_config: config which needs to contain 'num', 'mean', 'std' + """ + grid = 10 ** normal_grid(param_config, lognormal=True) + if "step" in param_config.keys(): + return round_to_discreate_grid_normal(grid, param_config) + return grid + + +def add_next_param_from_list(param_grid: dict, grid: dict, grid_df: pd.DataFrame): + """ + can be used in a recoursive fassion to add all combinations of the parameters in + param_grid to grid_df + param_grid: dictionary with all possible values for each parameter + {'p1': [1, 2, 3], 'p2': [0, 5], ...} + grid: a grid which will build itself in the recursion, start with grid = {} + after one step grid = {p1: 1} + grid_df: dataframe which will save the finished grids + task_name: task name + also: G_MODEL_NA name + """ + if len(param_grid.keys()) != 0: + # specify the parameter to be used + param_name = list(param_grid.keys())[0] + # for all values of this parameter perform + for param in param_grid[param_name]: + # add the parameter to the grid + grid_new = dict(grid) + grid_new.update({param_name: param}) + # remove the parameter from param_grid + param_grid_new = dict(param_grid) + param_grid_new.pop(param_name) + # resume with the next parameter + add_next_param_from_list(param_grid_new, grid_new, grid_df) + else: + # add sample to grid_df + grid_df.loc[len(grid_df.index)] = [grid] + + +def add_references_and_check_constraints( + grid_df_prior, grid_df, referenced_params, config, task_name +): + """ + in the last step all parameters which are referenced need to be add to the + grid. All gridpoints not satisfying the constraints are removed afterwards. + """ + for dictio in grid_df_prior["params"]: + for key, val in dictio.items(): + exec(f"{key} = val") + # add referenced params + for rev_param, val in referenced_params.items(): + val = eval(val) + dictio.update({rev_param: val}) + exec(f"{rev_param} = val") + # check constraints + if "hyperparameters" in config.keys(): + constraints = config["hyperparameters"].get("constraints", None) + else: + constraints = config.get("constraints", None) + if constraints is not None: + accepted = True + for constr in constraints: + if not eval(constr): + accepted = False + if accepted: + grid_df.loc[len(grid_df.index)] = [task_name, config["model"], dictio] + else: + grid_df.loc[len(grid_df.index)] = [task_name, config["model"], dictio] + + +def sample_grid(param_config): + """ + given the parameter config, this function samples all parameters which are distributed + according the the categorical, uniform, loguniform, normal or lognormal distribution. + """ + # sample cathegorical parameter + if param_config["distribution"] == "categorical": + param_grid = sampling.CategoricalHyperparameter("", param_config).allowed_values + # sample uniform parameter + elif param_config["distribution"] == "uniform": + param_grid = uniform_grid(param_config) + # sample loguniform parameter + elif param_config["distribution"] == "loguniform": + param_grid = loguniform_grid(param_config) + # sample normal parameter + elif param_config["distribution"] == "normal": + param_grid = normal_grid(param_config) + # sample lognormal parameter + elif param_config["distribution"] == "lognormal": + param_grid = lognormal_grid(param_config) + else: + raise RuntimeError( + f'distribution "{param_config["distribution"]}" not ' + f"implemented use a distribution from " + f"[categorical, uniform, loguniform, normal, lognormal]" + ) + + # ensure that the gird does have the correct datatype + # (only check for int, othervise float is used) + if "datatype" in param_config.keys(): + if param_config["datatype"] == "int": + param_grid = np.array(param_grid) + param_grid = param_grid.astype(int) + # NOTE: converting int to float will cause error for VAE, avoid do + # it here + return param_grid + + +def build_param_grid_of_shared_params(shared_df): + """ + go back from the data frame format of the shared hyperparamters to a list format + """ + if shared_df is None: + return None + shared_grid = {} + for key in shared_df["params"].iloc[0].keys(): + grid_points = [] + for i in shared_df["params"].keys(): + grid_points.append(shared_df["params"][i][key]) + shared_grid[key] = np.array(grid_points) + return shared_grid + + +def rais_error_if_num_not_specified(param_name: str, param_config: dict): + """ + for each parameter a number of grid points needs to be specified + This function raises an error if this is not the case + param_name: parameter name under consideration + param_config: config of this parameter + """ + if param_name == g_name_num_shared_param_samples_rand_search: + raise RuntimeError(f"{g_name_num_shared_param_samples_rand_search} only for random search!") + if not param_name == "constraints": + if ( + not "num" in param_config.keys() + and not "reference" in param_config.keys() + and not param_config["distribution"] == "categorical" + ): + raise RuntimeError( + f"the number of parameters in the grid direction " + f"of {param_name} needs to be specified" + ) + + +def add_shared_params_to_param_grids(shared_df, dict_param_grids, config): + """ + use the parameters in the dataframe of shared parameters and add them + to the dictionary of parameters for the current task + only the shared parameters specified in the config are respected + shared_df: Dataframe of shared hyperparameters + dict_param_grids: dictionary of the parameter grids + config: config for the current task + """ + dict_shared_grid = build_param_grid_of_shared_params(shared_df) + if "shared" in config.keys(): + list_names = config["shared"] + dict_shared_grid = {key: dict_shared_grid[key] for key in config["shared"]} + if dict_shared_grid is not None: + for key in dict_shared_grid.keys(): + dict_param_grids[key] = dict_shared_grid[key] + return dict_param_grids + + +def grid_task( + grid_df: pd.DataFrame, task_name: str, config: dict, shared_df: pd.DataFrame +): + """create grid for one sampling task for a method and add it to the dataframe""" + if "hyperparameters" in config.keys(): + dict_param_grids = {} + referenced_params = {} + for param_name in config["hyperparameters"].keys(): + param_config = config["hyperparameters"][param_name] + rais_error_if_num_not_specified(param_name, param_config) + + # constraints are not parameters + if not param_name == "constraints": + # remember all parameters which are reverenced + if "datatype" not in param_config.keys(): + warnings.warn( + f"datatype not specified in {param_config} \ + for {param_name}, take float as default" + ) + param_config["datatype"] = "float" + + if "reference" in param_config.keys(): + referenced_params.update({param_name: param_config["reference"]}) + # sample other parameter + elif param_name != "constraints": + dict_param_grids.update({param_name: sample_grid(param_config)}) + + # create the grid from the individual parameter grids + # constraints are not respected in this step + grid_df_prior = pd.DataFrame(columns=["params"]) + # add shared parameters to dict_param_grids + dict_param_grids = add_shared_params_to_param_grids( + shared_df, dict_param_grids, config + ) + add_next_param_from_list(dict_param_grids, {}, grid_df_prior) + + # add referenced params and check constraints + add_references_and_check_constraints( + grid_df_prior, grid_df, referenced_params, config, task_name + ) + if grid_df[grid_df[G_MODEL_NA] == config["model"]].shape[0] == 0: + raise RuntimeError( + "No valid value found for this grid spacing, refine grid" + ) + return grid_df + elif "shared" in config.keys(): + shared_grid = shared_df.copy() + shared_grid[G_MODEL_NA] = config["model"] + shared_grid[G_METHOD_NA] = task_name + if "constraints" in config.keys(): + config["hyperparameters"] = {"constraints": config["constraints"]} + add_references_and_check_constraints( + shared_grid, grid_df, {}, config, task_name + ) + return grid_df + else: + # add single line if no varying hyperparameters are specified. + grid_df.loc[len(grid_df.index)] = [task_name, config["model"], {}] + return grid_df + + +def sample_gridsearch(config: dict, dest: str = None) -> pd.DataFrame: + """ + create the hyperparameters grid according to the given + config, which should be the dictionary of the full + benchmark config yaml. + Result is saved to 'output_dir/hyperparameters.csv' of the + config if not specified explicitly. + + Note: Parts of the yaml content are executed. Thus use this + only with trusted config files. + """ + if dest is None: + dest = config["output_dir"] + os.sep + "hyperparameters.csv" + + logger = Logger.get_logger() + samples = pd.DataFrame(columns=[G_METHOD_NA, G_MODEL_NA, "params"]) + shared_samples_full = pd.DataFrame(columns=[G_METHOD_NA, G_MODEL_NA, "params"]) + + if "Shared params" in config.keys(): + shared_val = {"model": "all", "hyperparameters": config["Shared params"]} + # fill up the dataframe shared samples + shared_samples_full = grid_task(shared_samples_full, "all", shared_val, None) + else: + shared_samples_full = None + for key, val in config.items(): + if sampling.is_dict_with_key(val, "model"): + if shared_samples_full is not None: + shared_samples = shared_samples_full.copy(deep=True) + if "shared" in val.keys(): + shared = val["shared"] + else: + shared = [] + for line_num in range(shared_samples.shape[0]): + hyper_p_dict = shared_samples.iloc[line_num]["params"].copy() + key_list = copy.deepcopy(list(hyper_p_dict.keys())) + if not all(x in key_list for x in shared): + raise RuntimeError( + f"shared keys: {shared} not included in global shared keys {key_list}" + ) + for key_ in key_list: + if key_ not in shared: + del hyper_p_dict[key_] + shared_samples.iloc[line_num]["params"] = hyper_p_dict + # remove all duplicates + shared_samples = shared_samples.drop_duplicates(subset="params") + else: + shared_samples = None + + samples = grid_task(samples, key, val, shared_samples) + logger.info( + f"number of gridpoints for {key} : " + f'{samples[samples[G_MODEL_NA] == val["model"]].shape[0]}' + ) + + os.makedirs(os.path.dirname(dest), exist_ok=True) + logger.info(f"number of total sampled gridpoints: {samples.shape[0]}") + samples.to_csv(dest) + # create a txt file with the commit information + with open( + config["output_dir"] + os.sep + "commit.txt", "w", encoding="utf8" + ) as file: + file.writelines("use git log |grep \n") + file.writelines("consider remove leading b in the line below \n") + file.write(get_git_tag()) + with open( + config["output_dir"] + os.sep + "config.txt", "w", encoding="utf8" + ) as file: + json.dump(config, file) + return samples diff --git a/domainlab/utils/hyperparameter_sampling.py b/domainlab/utils/hyperparameter_sampling.py index fc500a7f7..14c1f42e4 100644 --- a/domainlab/utils/hyperparameter_sampling.py +++ b/domainlab/utils/hyperparameter_sampling.py @@ -1,14 +1,27 @@ """ Samples the hyperparameters according to a benchmark configuration file. + +# Structure of this file: +- Class Hyperparameter +# Inherited Classes +# Functions to sample hyper-parameters and log into csv file """ +import copy +import json import os +from ast import literal_eval # literal_eval can safe evaluate python expression from pydoc import locate from typing import List -from ast import literal_eval # literal_eval can safe evaluate python expression import numpy as np import pandas as pd +from domainlab.utils.get_git_tag import get_git_tag +from domainlab.utils.logger import Logger + +G_MODEL_NA = "model" +G_METHOD_NA = "method" + class Hyperparameter: """ @@ -20,6 +33,7 @@ class Hyperparameter: p2: max or scale reference: None or name of referenced hyperparameter """ + def __init__(self, name: str): self.name = name self.val = 0 @@ -48,19 +62,22 @@ class SampledHyperparameter(Hyperparameter): """ A numeric hyperparameter that shall be sampled """ + def __init__(self, name: str, config: dict): super().__init__(name) - self.step = config.get('step', 0) + self.step = config.get("step", 0) try: - self.distribution = config['distribution'] - if self.distribution in {'uniform', 'loguniform'}: - self.p_1 = config['min'] - self.p_2 = config['max'] - elif self.distribution in {'normal', 'lognormal'}: - self.p_1 = config['mean'] - self.p_2 = config['std'] + self.distribution = config["distribution"] + if self.distribution in {"uniform", "loguniform"}: + self.p_1 = config["min"] + self.p_2 = config["max"] + elif self.distribution in {"normal", "lognormal"}: + self.p_1 = config["mean"] + self.p_2 = config["std"] else: - raise RuntimeError(f"Unsupported distribution type: {self.distribution}.") + raise RuntimeError( + f"Unsupported distribution type: {self.distribution}." + ) except KeyError as ex: raise RuntimeError(f"Missing required key for parameter {name}.") from ex @@ -70,10 +87,14 @@ def __init__(self, name: str, config: dict): def _ensure_step(self): """Make sure that the hyperparameter sticks to the discrete grid""" if self.step == 0: - return # continous parameter + return # continous parameter # round to next discrete value. + # p_1 is the lower bound of the hyper-parameter range, p_2 the upper bound off = (self.val - self.p_1) % self.step + # $off$ is always smaller than step, depending on whether $off$ falls on the left half + # or right half of [0, step], move the hyper-parameter to the boundary so that + # updated hyper-parameter % step = 0 if off < self.step / 2: self.val -= off else: @@ -84,13 +105,13 @@ def _ensure_step(self): def sample(self): """Sample this parameter, respecting properties""" - if self.distribution == 'uniform': + if self.distribution == "uniform": self.val = np.random.uniform(self.p_1, self.p_2) - elif self.distribution == 'loguniform': + elif self.distribution == "loguniform": self.val = 10 ** np.random.uniform(np.log10(self.p_1), np.log10(self.p_2)) - elif self.distribution == 'normal': + elif self.distribution == "normal": self.val = np.random.normal(self.p_1, self.p_2) - elif self.distribution == 'lognormal': + elif self.distribution == "lognormal": self.val = 10 ** np.random.normal(self.p_1, self.p_2) else: raise RuntimeError(f"Unsupported distribution type: {self.distribution}.") @@ -105,9 +126,10 @@ class ReferenceHyperparameter(Hyperparameter): Hyperparameter that references only a different one. Thus, this parameter is not sampled but set after sampling. """ + def __init__(self, name: str, config: dict): super().__init__(name) - self.reference = config.get('reference', None) + self.reference = config.get("reference", None) def _ensure_step(self): """Make sure that the hyperparameter sticks to the discrete grid""" @@ -128,10 +150,15 @@ class CategoricalHyperparameter(Hyperparameter): A sampled hyperparameter, which is constraint to fixed, user given values and datatype """ + def __init__(self, name: str, config: dict): super().__init__(name) - self.allowed_values = config['values'] - self.type = locate(config['datatype']) + self.allowed_values = config["values"] + if "datatype" not in config: + raise RuntimeError( + "Please specifiy datatype for all categorical hyper-parameters!, e.g. datatype=str" + ) + self.type = locate(config["datatype"]) self.allowed_values = [self.type(v) for v in self.allowed_values] def _ensure_step(self): @@ -151,10 +178,10 @@ def datatype(self): def get_hyperparameter(name: str, config: dict) -> Hyperparameter: """Factory function. Instantiates the correct Hyperparameter""" - if 'reference' in config.keys(): + if "reference" in config.keys(): return ReferenceHyperparameter(name, config) - dist = config.get('distribution', None) - if dist == 'categorical': + dist = config.get("distribution", None) + if dist == "categorical": return CategoricalHyperparameter(name, config) return SampledHyperparameter(name, config) @@ -170,15 +197,16 @@ def check_constraints(params: List[Hyperparameter], constraints) -> bool: for par in params: if isinstance(par, ReferenceHyperparameter): try: - setattr(par, 'val', eval(par.reference)) + setattr(par, "val", eval(par.reference)) # NOTE: literal_eval will cause ValueError: malformed node or string except Exception as ex: - print(f"error in evaluating expression: {par.reference}") + logger = Logger.get_logger() + logger.info(f"error in evaluating expression: {par.reference}") raise ex locals().update({par.name: par.val}) if constraints is None: - return True # shortcut + return True # shortcut # check all constraints for constr in constraints: @@ -193,7 +221,12 @@ def check_constraints(params: List[Hyperparameter], constraints) -> bool: return True -def sample_parameters(params: List[Hyperparameter], constraints) -> dict: +def sample_parameters( + init_params: List[Hyperparameter], + constraints, + shared_config=None, + shared_samples=None, +) -> dict: """ Tries to sample from the hyperparameter list. @@ -201,43 +234,198 @@ def sample_parameters(params: List[Hyperparameter], constraints) -> dict: constraints is found. """ for _ in range(10_000): + params = copy.deepcopy(init_params) + for par in params: + par.sample() + # add a random hyperparameter from the shared hyperparameter dataframe + if shared_samples is not None: + # sample one line from the pandas dataframe + shared_samp = shared_samples.sample(1).iloc[0]["params"] + for key in shared_samp.keys(): + par = Hyperparameter(key) + par.val = shared_samp[key] + par.name = key + params.append(par) + # check constrained + if check_constraints(params, constraints): + samples = {} + for par in params: + samples[par.name] = par.val + return samples + + # if there was no sample found fullfilling the constrained above, + # this may be due to the shared hyperparameters. + # If so, new samples are generated for the shared hyperparameters + logger = Logger.get_logger() + logger.warning( + "The constrainds coundn't be met with the shared Hyperparameters, " + "shared dataframe pool will be ignored for now." + ) + for _ in range(10_000): + params = copy.deepcopy(init_params) + # add the shared hyperparameter as a sampled hyperparameter + if shared_samples is not None: + shared_samp = shared_samples.sample(1).iloc[0]["params"] + for key in shared_samp.keys(): + par = SampledHyperparameter(key, shared_config[key]) + par.sample() + par.name = key + params.append(par) for par in params: par.sample() + # check constrained if check_constraints(params, constraints): samples = {} for par in params: samples[par.name] = par.val return samples - raise RuntimeError("Could not find an acceptable sample in 10,000 runs." - "Are the bounds and constraints reasonable?") + raise RuntimeError( + "Could not find an acceptable sample in 10,000 runs." + "Are the bounds and constraints reasonable?" + ) -def sample_task(num_samples: int, sample_df: pd.DataFrame, task_name: str, config: dict): +def create_samples_from_shared_samples( + shared_samples: pd.DataFrame, config: dict, task_name: str +): + """ + add informations like task, G_MODEL_NA and constrainds to the shared samples + Parameters: + shared_samples: pd Dataframe with columns [G_METHOD_NA, G_MODEL_NA, 'params'] + config: dataframe with yaml configuration of the current task + task_name: name of the current task + """ + shared_samp = shared_samples.copy() + shared_samp[G_MODEL_NA] = config["model"] + shared_samp[G_METHOD_NA] = task_name + # respect the constraints if specified in the task + if "constraints" in config.keys(): + for idx in range(shared_samp.shape[0] - 1, -1, -1): + name = list(shared_samp["params"].iloc[idx].keys())[0] + value = shared_samp["params"].iloc[idx][name] + par = Hyperparameter(name) + par.val = value + if not check_constraints([par], config["constraints"]): + shared_samp = shared_samp.drop(idx) + return shared_samp + + +def sample_task_only_shared( + num_samples, task_name, sample_df, config, shared_conf_samp +): + """ + sample one task and add it to the dataframe for task descriptions which only + contain shared hyperparameters + """ + shared_config, shared_samples = shared_conf_samp + # copy the shared samples dataframe and add the corrct G_MODEL_NA and taks names + shared_samp = create_samples_from_shared_samples(shared_samples, config, task_name) + + # for the case that we expect more hyperparameter samples for the G_MODEL_NArithm as provided + # in the shared sampes we use the shared config to sample new hyperparameters to ensure + # that we have distinct hyperparameters + if num_samples - shared_samp.shape[0] > 0: + s_config = shared_config.copy() + s_dict = {} + for keys in s_config.keys(): + if keys != "num_shared_param_samples": + s_dict[keys] = s_config[keys] + if "constraints" in config.keys(): + s_dict["constraints"] = config["constraints"] + s_config["model"] = config["model"] + s_config["hyperparameters"] = s_dict + + # sample new shared hyperparameters + sample_df = sample_task( + num_samples - shared_samp.shape[0], + task_name, + (s_config, sample_df), + (None, None), + ) + # add previously sampled shared hyperparameters + sample_df = sample_df.append(shared_samp, ignore_index=True) + # for the case that the number of shared samples is >= the expected number of + # sampled hyperparameters we randomly choose rows in the sampled hyperparameters df + else: + shared_samp = shared_samp.sample(num_samples) + sample_df = sample_df.append(shared_samp, ignore_index=True) + + return sample_df + + +def sample_task( + num_samples: int, task_name: str, conf_samp: tuple, shared_conf_samp: tuple +): """Sample one task and add it to the dataframe""" - algo = config['aname'] - if 'hyperparameters' in config.keys(): + config, sample_df = conf_samp + shared_config, shared_samples = shared_conf_samp + if "hyperparameters" in config.keys(): + # in benchmark configuration file, sub-section hyperparameters + # means changing hyper-parameters params = [] - for key, val in config['hyperparameters'].items(): - if key == 'constraints': + for key, val in config["hyperparameters"].items(): + if key in ("constraints", "num_shared_param_samples"): continue params += [get_hyperparameter(key, val)] - constraints = config['hyperparameters'].get('constraints', None) + constraints = config["hyperparameters"].get("constraints", None) for _ in range(num_samples): - sample = sample_parameters(params, constraints) - sample_df.loc[len(sample_df.index)] = [task_name, algo, sample] + sample = sample_parameters( + params, constraints, shared_config, shared_samples + ) + sample_df.loc[len(sample_df.index)] = [task_name, config["model"], sample] + elif "shared" in config.keys(): + sample_df = sample_task_only_shared( + num_samples, task_name, sample_df, config, (shared_config, shared_samples) + ) else: # add single line if no varying hyperparameters are specified. - sample_df.loc[len(sample_df.index)] = [task_name, algo, {}] + sample_df.loc[len(sample_df.index)] = [task_name, config["model"], {}] + return sample_df + +def is_dict_with_key(input_dict, key) -> bool: + """Determines if the input argument is a dictionary and it has key""" + return isinstance(input_dict, dict) and key in input_dict.keys() -def is_task(val) -> bool: - """Determines if the value of this key is a task.""" - return isinstance(val, dict) and 'aname' in val.keys() +def get_shared_samples( + shared_samples_full: pd.DataFrame, shared_config_full: dict, task_config: dict +): + """ + - creates a dataframe with columns [task, G_MODEL_NA, params], + task and G_MODEL_NA are all for all rows, but params is filled with the + shared parameters of shared_samples_full requested by task_config. -def sample_hyperparameters(config: dict, dest: str = None) -> pd.DataFrame: + - creates a shared config containing only information about the + shared hyperparameters requested by the task_config + """ + shared_samples = shared_samples_full.copy(deep=True) + shared_config = shared_config_full.copy() + if "shared" in task_config.keys(): + shared = task_config["shared"] + else: + shared = [] + for line_num in range(shared_samples.shape[0]): + hyper_p_dict = shared_samples.iloc[line_num]["params"].copy() + key_list = copy.deepcopy(list(hyper_p_dict.keys())) + for key_ in key_list: + if key_ not in shared: + del hyper_p_dict[key_] + shared_samples.iloc[line_num]["params"] = hyper_p_dict + for key_ in key_list: + if not key_ == "num_shared_param_samples": + if key_ not in shared: + del shared_config[key_] + # remove all duplicates + shared_samples = shared_samples.drop_duplicates(subset="params") + return shared_samples, shared_config + + +def sample_hyperparameters( + config: dict, dest: str = None, sampling_seed: int = None +) -> pd.DataFrame: """ Samples the hyperparameters according to the given config, which should be the dictionary of the full @@ -249,17 +437,53 @@ def sample_hyperparameters(config: dict, dest: str = None) -> pd.DataFrame: only with trusted config files. """ if dest is None: - dest = config['output_dir'] + os.sep + 'hyperparameters.csv' - - if 'sampling_seed' in config.keys(): - np.random.seed(config['sampling_seed']) - - num_samples = config['num_param_samples'] - samples = pd.DataFrame(columns=['task', 'algo', 'params']) + dest = config["output_dir"] + os.sep + "hyperparameters.csv" + + if sampling_seed is not None: + np.random.seed(sampling_seed) + + num_samples = config["num_param_samples"] + samples = pd.DataFrame(columns=[G_METHOD_NA, G_MODEL_NA, "params"]) + if "Shared params" in config.keys(): + shared_config_full = config["Shared params"] + shared_samples_full = pd.DataFrame(columns=[G_METHOD_NA, G_MODEL_NA, "params"]) + shared_val = {"model": "all", "hyperparameters": config["Shared params"]} + # fill up the dataframe shared samples + shared_samples_full = sample_task( + shared_config_full["num_shared_param_samples"], + "all", + (shared_val, shared_samples_full), + (None, None), + ) + else: + shared_samples_full = None for key, val in config.items(): - if is_task(val): - sample_task(num_samples, samples, key, val) + if is_dict_with_key(val, "model"): + if shared_samples_full is not None: + shared_samples, shared_config = get_shared_samples( + shared_samples_full, shared_config_full, val + ) + else: + shared_config = None + shared_samples = None + + samples = sample_task( + num_samples, key, (val, samples), (shared_config, shared_samples) + ) os.makedirs(os.path.dirname(dest), exist_ok=True) + + # create a txt file with the commit information + with open( + config["output_dir"] + os.sep + "commit.txt", "w", encoding="utf8" + ) as file: + file.writelines("use git log |grep \n") + file.writelines("consider remove leading b in the line below \n") + file.write(get_git_tag()) + with open( + config["output_dir"] + os.sep + "config.txt", "w", encoding="utf8" + ) as file: + json.dump(config, file) + samples.to_csv(dest) return samples diff --git a/domainlab/utils/logger.py b/domainlab/utils/logger.py new file mode 100644 index 000000000..31260e796 --- /dev/null +++ b/domainlab/utils/logger.py @@ -0,0 +1,46 @@ +""" +A logger for our software +""" +import logging +import multiprocessing +import os + + +class Logger: + """ + static logger class + """ + + logger = None + + @staticmethod + def get_logger( + logger_name="logger_" + str(multiprocessing.current_process().pid), + loglevel="INFO", + ): + """ + returns a logger + if no logger was created yet, it will create a logger with the name + specified in logger_name with the level specified in loglevel. + If the logger was created for the first time the arguments do not change + anything at the behaviour anymore + """ + if Logger.logger is None: + Logger.logger = logging.getLogger(logger_name) + Logger.logger.setLevel(loglevel) + + # Create handlers and set their logging level + logfolder = "zoutput/logs" + os.makedirs(logfolder, exist_ok=True) + # Create handlers and set their logging level + filehandler = logging.FileHandler( + logfolder + "/" + Logger.logger.name + ".log", mode="w" + ) + filehandler.setLevel(loglevel) + + console_handler = logging.StreamHandler() + console_handler.setLevel(loglevel) + # Add handlers to logger + Logger.logger.addHandler(filehandler) + Logger.logger.addHandler(console_handler) + return Logger.logger diff --git a/domainlab/utils/override_interface.py b/domainlab/utils/override_interface.py index 9eaef4c83..8c0c8025e 100644 --- a/domainlab/utils/override_interface.py +++ b/domainlab/utils/override_interface.py @@ -13,6 +13,7 @@ class Child(BaseClass): def fun(self): pass """ + def overrider(method2override): """overrider. diff --git a/domainlab/utils/perf.py b/domainlab/utils/perf.py index 7e52aa817..05c77cfd2 100644 --- a/domainlab/utils/perf.py +++ b/domainlab/utils/perf.py @@ -2,13 +2,15 @@ import torch -class PerfClassif(): +class PerfClassif: """Classification Performance""" + @classmethod def gen_fun_acc(cls, dim_target): """ :param dim_target: class/domain label embeding dimension """ + def fun_acc(list_vec_preds, list_vec_labels): """ :param list_vec_preds: list of batches @@ -17,7 +19,9 @@ def fun_acc(list_vec_preds, list_vec_labels): correct_count = 0 obs_count = 0 for pred, label in zip(list_vec_preds, list_vec_labels): - correct_count += torch.sum(torch.sum(pred == label, dim=1) == dim_target) + correct_count += torch.sum( + torch.sum(pred == label, dim=1) == dim_target + ) obs_count += pred.shape[0] # batch size if isinstance(correct_count, int): acc = (correct_count) / obs_count @@ -26,33 +30,36 @@ def fun_acc(list_vec_preds, list_vec_labels): # AttributeError: 'int' object has no attribute 'float' # reason: batchsize is too big return acc + return fun_acc @classmethod - def cal_acc(cls, model, loader_te, device, max_batches=None): + def cal_acc(cls, model, loader_te, device): """ :param model: :param loader_te: :param device: for final test, GPU can be used - :param max_batches: - maximum number of iteration for data loader, used to - probe performance with less computation burden. - default None, which means to traverse the whole dataset """ model.eval() model_local = model.to(device) - if max_batches is None: - max_batches = len(loader_te) - fun_acc = cls.gen_fun_acc(model_local.dim_y) + fun_acc = cls.gen_fun_acc(model_local.dim_y) + list_vec_preds, list_vec_labels = cls.get_list_pred_target( + model_local, loader_te, device + ) + accuracy_y = fun_acc(list_vec_preds, list_vec_labels) + acc_y = accuracy_y.cpu().numpy().item() + return acc_y + + @classmethod + def get_list_pred_target(cls, model_local, loader_te, device): + """ + isolate function to check if prediction persist each time loader is went through + """ list_vec_preds, list_vec_labels = [], [] with torch.no_grad(): - for i, (x_s, y_s, *_) in enumerate(loader_te): + for _, (x_s, y_s, *_) in enumerate(loader_te): x_s, y_s = x_s.to(device), y_s.to(device) pred, *_ = model_local.infer_y_vpicn(x_s) list_vec_preds.append(pred) list_vec_labels.append(y_s) - if i > max_batches: - break - accuracy_y = fun_acc(list_vec_preds, list_vec_labels) - acc_y = accuracy_y.cpu().numpy().item() - return acc_y + return list_vec_preds, list_vec_labels diff --git a/domainlab/utils/perf_metrics.py b/domainlab/utils/perf_metrics.py index f12cd6015..932d1f9ab 100644 --- a/domainlab/utils/perf_metrics.py +++ b/domainlab/utils/perf_metrics.py @@ -1,32 +1,46 @@ """Classification Performance""" +import numpy as np import torch -from torchmetrics.classification import (AUC, AUROC, Accuracy, ConfusionMatrix, - F1Score, Precision, Recall, - Specificity) +from torchmetrics.classification import ( + AUC, + AUROC, + Accuracy, + ConfusionMatrix, + F1Score, + Precision, + Recall, + Specificity, +) -class PerfMetricClassif(): +class PerfMetricClassif: """Classification Performance metrics""" - def __init__(self, num_classes, average='macro'): + + def __init__(self, num_classes, agg_precision_recall_f1="macro"): super().__init__() - self.acc = Accuracy(num_classes=num_classes, average=average) - self.precision = Precision(num_classes=num_classes, average=average) - self.recall = Recall(num_classes=num_classes, average=average) - self.f1_score = F1Score(num_classes=num_classes, average=average) - self.auroc = AUROC(num_classes=num_classes, average=average) - self.specificity = Specificity(num_classes=num_classes, - average=average) + self.acc = Accuracy(num_classes=num_classes, average="micro") + # NOTE: only micro aggregation make sense for acc + self.precision = Precision( + num_classes=num_classes, average=agg_precision_recall_f1 + ) + # Calculate the metric for each class separately, and average the + # metrics across classes (with equal weights for each class). + self.recall = Recall(num_classes=num_classes, average=agg_precision_recall_f1) + self.f1_score = F1Score( + num_classes=num_classes, average=agg_precision_recall_f1 + ) + # NOTE: auroc does nto support "micro" as aggregation + self.auroc = AUROC(num_classes=num_classes, average=agg_precision_recall_f1) + self.specificity = Specificity( + num_classes=num_classes, average=agg_precision_recall_f1 + ) self.confmat = ConfusionMatrix(num_classes=num_classes) - def cal_metrics(self, model, loader_te, device, max_batches=None): + def cal_metrics(self, model, loader_te, device): """ :param model: :param loader_te: :param device: for final test, GPU can be used - :param max_batches: - maximum number of iteration for data loader, used to - probe performance with less computation burden. - default None, which means to traverse the whole dataset """ self.acc.reset() self.precision.reset() @@ -42,12 +56,10 @@ def cal_metrics(self, model, loader_te, device, max_batches=None): self.auroc = self.auroc.to(device) self.specificity = self.specificity.to(device) self.confmat = self.confmat.to(device) - model.eval() model_local = model.to(device) - if max_batches is None: - max_batches = len(loader_te) + model_local.eval() with torch.no_grad(): - for i, (x_s, y_s, *_) in enumerate(loader_te): + for _, (x_s, y_s, *_) in enumerate(loader_te): x_s, y_s = x_s.to(device), y_s.to(device) _, prob, _, *_ = model_local.infer_y_vpicn(x_s) _, target_label = torch.max(y_s, 1) @@ -61,8 +73,6 @@ def cal_metrics(self, model, loader_te, device, max_batches=None): self.f1_score.update(prob, target_label) self.auroc.update(prob, target_label) self.confmat.update(prob, target_label) - if i > max_batches: - break acc_y = self.acc.compute() precision_y = self.precision.compute() @@ -71,13 +81,15 @@ def cal_metrics(self, model, loader_te, device, max_batches=None): f1_score_y = self.f1_score.compute() auroc_y = self.auroc.compute() confmat_y = self.confmat.compute() - dict_metric = {"acc": acc_y, - "precision": precision_y, - "recall": recall_y, - "specificity": specificity_y, - "f1": f1_score_y, - "auroc": auroc_y, - "confmat": confmat_y} + dict_metric = { + "acc": acc_y, + "precision": precision_y, + "recall": recall_y, + "specificity": specificity_y, + "f1": f1_score_y, + "auroc": auroc_y, + "confmat": confmat_y, + } keys = list(dict_metric) keys.remove("confmat") for key in keys: diff --git a/domainlab/utils/sanity_check.py b/domainlab/utils/sanity_check.py new file mode 100644 index 000000000..6994c496d --- /dev/null +++ b/domainlab/utils/sanity_check.py @@ -0,0 +1,93 @@ +""" +This class is used to perform the sanity check on a task description +""" + +import datetime +import os +import shutil + +import numpy as np +import torch.utils.data as data_utils +from torch.utils.data import Subset + +from domainlab.dsets.utils_data import plot_ds + + +class SanityCheck: + """ + Performs a sanity check on the given args and the task + when running dataset_sanity_check(self) + """ + + def __init__(self, args, task): + self.args = args + self.task = task + + def dataset_sanity_check(self): + """ + when we load data from folder or a file listing the path of observations, + we want to check if the file we loaded are in accordance with our expectations + This function dump a subsample of the dataset into hierarchical folder structure. + """ + # self.task.init_business(self.args) + + list_domain_tr, list_domain_te = self.task.get_list_domains_tr_te( + self.args.tr_d, self.args.te_d + ) + + time_stamp = datetime.datetime.now() + f_name = os.path.join( + self.args.out, + "Dset_extraction", + self.task.task_name + " " + str(time_stamp), + ) + # remove previous sanity checks with the same name + shutil.rmtree(f_name, ignore_errors=True) + + # for each training domain do... + for domain in list_domain_tr: + if domain in self.task.dict_dset_tr: + d_dataset = self.task.dict_dset_tr[domain] + else: + d_dataset = self.task.get_dset_by_domain(self.args, domain)[0] + folder_name = f_name + "/train_domain/" + str(domain) + self.save_san_check_for_domain(self.args.san_num, folder_name, d_dataset) + + # for each testing domain do... + for domain in list_domain_te: + if domain in self.task.dict_dset_te: + d_dataset = self.task.dict_dset_te[domain] + else: + d_dataset = self.task.get_dset_by_domain(self.args, domain)[0] + folder_name = f_name + "/test_domain/" + str(domain) + self.save_san_check_for_domain(self.args.san_num, folder_name, d_dataset) + + def save_san_check_for_domain(self, sample_num, folder_name, d_dataset): + """ + saves a extraction of the dataset (d_dataset) into folder (folder_name) + sample_num: int, number of images which are extracted from the dataset + folder_name: string, destination for the saved images + d_dataset: dataset + """ + + # for each class do... + for class_num in range(len(self.task.list_str_y)): + num_of_samples = 0 + loader_domain = data_utils.DataLoader( + d_dataset, batch_size=1, shuffle=False + ) + domain_targets = [] + for num, (_, lab, *_) in enumerate(loader_domain): + if int(np.argmax(lab[0])) == class_num: + domain_targets.append(num) + num_of_samples += 1 + if sample_num == num_of_samples: + break + + class_dataset = Subset(d_dataset, domain_targets) + os.makedirs(folder_name, exist_ok=True) + plot_ds( + class_dataset, + folder_name + "/" + str(self.task.list_str_y[class_num]) + ".jpg", + batchsize=sample_num, + ) diff --git a/domainlab/utils/test_img.py b/domainlab/utils/test_img.py index 16902a46c..f401aa337 100644 --- a/domainlab/utils/test_img.py +++ b/domainlab/utils/test_img.py @@ -5,18 +5,22 @@ def mk_img(i_h, i_ch=3, batch_size=5): img = torch.rand(i_h, i_h) # uniform distribution [0,1] # x = torch.clamp(x, 0, 1) img.unsqueeze_(0) - img = img.repeat(i_ch, 1, 1) # RGB image + img = img.repeat(i_ch, 1, 1) # RGB image img.unsqueeze_(0) img = img.repeat(batch_size, 1, 1, 1) return img + def mk_rand_label_onehot(target_dim=10, batch_size=5): - label_scalar = torch.randint(high=target_dim, size=(batch_size, )) + label_scalar = torch.randint(high=target_dim, size=(batch_size,)) label_scalar2 = label_scalar.unsqueeze(1) label_zeros = torch.zeros(batch_size, target_dim) - label_onehot = torch.scatter(input=label_zeros, dim=1, index=label_scalar2, value=1.0) + label_onehot = torch.scatter( + input=label_zeros, dim=1, index=label_scalar2, value=1.0 + ) return label_onehot + def mk_rand_xyd(ims, y_dim, d_dim, batch_size): imgs = mk_img(i_h=ims, batch_size=batch_size) ys = mk_rand_label_onehot(target_dim=y_dim, batch_size=batch_size) diff --git a/domainlab/utils/u_import_net_module.py b/domainlab/utils/u_import_net_module.py index 0783631f9..14df0fcc5 100644 --- a/domainlab/utils/u_import_net_module.py +++ b/domainlab/utils/u_import_net_module.py @@ -2,12 +2,12 @@ import external neural network implementation """ +from domainlab.utils.logger import Logger from domainlab.utils.u_import import import_path -def build_external_obj_net_module_feat_extract(mpath, dim_y, - remove_last_layer): - """ The user provide a function to initiate an object of the neural network, +def build_external_obj_net_module_feat_extract(mpath, dim_y, remove_last_layer): + """The user provide a function to initiate an object of the neural network, which is fine for training but problematic for persistence of the trained model since it is created externally. :param mpath: path of external python file where the neural network @@ -28,19 +28,25 @@ def build_external_obj_net_module_feat_extract(mpath, dim_y, name_signature = "build_feat_extract_net(dim_y, \ remove_last_layer)" # @FIXME: hard coded, move to top level __init__ definition in domainlab - name_fun = name_signature[:name_signature.index("(")] + name_fun = name_signature[: name_signature.index("(")] if hasattr(net_module, name_fun): try: net = getattr(net_module, name_fun)(dim_y, remove_last_layer) except Exception: - print("function %s should return a neural network (pytorch module) that \ - that extract features from an image" % (name_signature)) + logger = Logger.get_logger() + logger.error( + f"function {name_signature} should return a neural network " + f"(pytorch module) that that extract features from an image" + ) raise if net is None: - raise RuntimeError("the pytorch module returned by %s is None" - % (name_signature)) + raise RuntimeError( + "the pytorch module returned by %s is None" % (name_signature) + ) else: - raise RuntimeError("Please implement a function %s \ + raise RuntimeError( + "Please implement a function %s \ in your external python file" - % (name_signature)) + % (name_signature) + ) return net diff --git a/domainlab/utils/utils_class.py b/domainlab/utils/utils_class.py index 96963689d..3e0e9895e 100644 --- a/domainlab/utils/utils_class.py +++ b/domainlab/utils/utils_class.py @@ -3,13 +3,11 @@ def store_args(method): - """Stores provided method args as instance attributes. - """ + """Stores provided method args as instance attributes.""" argspec = inspect.getfullargspec(method) defaults = {} if argspec.defaults is not None: - defaults = dict( - zip(argspec.args[-len(argspec.defaults):], argspec.defaults)) + defaults = dict(zip(argspec.args[-len(argspec.defaults) :], argspec.defaults)) if argspec.kwonlydefaults is not None: defaults.update(argspec.kwonlydefaults) arg_names = argspec.args[1:] diff --git a/domainlab/utils/utils_classif.py b/domainlab/utils/utils_classif.py index 51f858dec..2948f3289 100644 --- a/domainlab/utils/utils_classif.py +++ b/domainlab/utils/utils_classif.py @@ -26,12 +26,15 @@ def logit2preds_vpic(logit): one_hot = one_hot.scatter_(dim=1, index=max_ind, value=1.0) return one_hot, mat_prob, max_ind, max_prob + def get_label_na(tensor_ind, list_str_na): """ given list of label names in strings, map tensor of index to label names """ arr_ind_np = tensor_ind.cpu().numpy() - arr_ind = np.squeeze(arr_ind_np, axis=1) # explicitly use axis=1 to deal with edge case of only + arr_ind = np.squeeze( + arr_ind_np, axis=1 + ) # explicitly use axis=1 to deal with edge case of only # instance left # list_ind = list(arr_ind): if there is only dimension 1 tensor_ind, then there is a problem list_ind = arr_ind.tolist() diff --git a/domainlab/utils/utils_cuda.py b/domainlab/utils/utils_cuda.py index ba3447fed..bf72776a3 100644 --- a/domainlab/utils/utils_cuda.py +++ b/domainlab/utils/utils_cuda.py @@ -1,10 +1,23 @@ +""" +choose devices +""" import torch +from domainlab.utils.logger import Logger -def get_device(flag_no_cu): + +def get_device(args): + """ + choose devices + """ + flag_no_cu = args.nocu flag_cuda = torch.cuda.is_available() and (not flag_no_cu) - device = torch.device("cuda" if flag_cuda else "cpu") - print("") - print("using device:", str(device)) - print("") + if args.device is None: + device = torch.device("cuda" if flag_cuda else "cpu") + else: + device = torch.device("cuda:" + args.device if flag_cuda else "cpu") + logger = Logger.get_logger() + logger.info("") + logger.info(f"using device: {str(device)}") + logger.info("") return device diff --git a/domainlab/utils/utils_img_sav.py b/domainlab/utils/utils_img_sav.py index e586e0e0d..d5ae50c4f 100644 --- a/domainlab/utils/utils_img_sav.py +++ b/domainlab/utils/utils_img_sav.py @@ -4,6 +4,8 @@ import matplotlib.pyplot as plt from torchvision.utils import make_grid, save_image +from domainlab.utils.logger import Logger + def mk_fun_sav_img(path=".", nrow=8, folder_na=""): """ @@ -14,7 +16,8 @@ def mk_fun_sav_img(path=".", nrow=8, folder_na=""): def my_sav_img(comparison_tensor_stack, name, title=None): f_p = os.path.join(path, folder_na, name) Path(os.path.dirname(f_p)).mkdir(parents=True, exist_ok=True) - print("saving to ", f_p) + logger = Logger.get_logger() + logger.info(f"saving to {f_p}") # works also if tensor is already in cpu tensor = comparison_tensor_stack.cpu() if title is None: @@ -22,6 +25,7 @@ def my_sav_img(comparison_tensor_stack, name, title=None): else: img_grid = make_grid(tensor=tensor, nrow=nrow) sav_add_title(img_grid, path=f_p, title="hi") + return my_sav_img @@ -29,7 +33,7 @@ def sav_add_title(grid_img, path, title): """ add title and save image as matplotlib.pyplot """ - fig = plt.gcf() # get current figure + fig = plt.gcf() # get current figure plt.imshow(grid_img.permute(1, 2, 0)) plt.title(title) fig.savefig(path) diff --git a/domainlab/zdata/mixed_codec/caltech/auto/text.txt b/domainlab/zdata/mixed_codec/caltech/auto/text.txt new file mode 100644 index 000000000..557db03de --- /dev/null +++ b/domainlab/zdata/mixed_codec/caltech/auto/text.txt @@ -0,0 +1 @@ +Hello World diff --git a/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_150.jpg b/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_150.jpg new file mode 100644 index 000000000..8d01af8c3 Binary files /dev/null and b/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_150.jpg differ diff --git a/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_151.jpg b/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_151.jpg new file mode 100644 index 000000000..4d1bdc631 Binary files /dev/null and b/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_151.jpg differ diff --git a/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_152.png b/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_152.png new file mode 100644 index 000000000..7582a9d15 Binary files /dev/null and b/domainlab/zdata/mixed_codec/caltech/auto/train_imgs_152.png differ diff --git a/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_1.jpg b/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_1.jpg new file mode 100644 index 000000000..36e8af5d6 Binary files /dev/null and b/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_1.jpg differ diff --git a/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_2.jpg b/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_2.jpg new file mode 100644 index 000000000..5affad9fb Binary files /dev/null and b/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_2.jpg differ diff --git a/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_3.png b/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_3.png new file mode 100644 index 000000000..85448b532 Binary files /dev/null and b/domainlab/zdata/mixed_codec/caltech/vogel/train_imgs_3.png differ diff --git a/domainlab/zdata/mixed_codec/sun/sofa/train_imgs_609.jpg b/domainlab/zdata/mixed_codec/sun/sofa/train_imgs_609.jpg new file mode 100644 index 000000000..239adbfcc Binary files /dev/null and b/domainlab/zdata/mixed_codec/sun/sofa/train_imgs_609.jpg differ diff --git a/domainlab/zdata/mixed_codec/sun/sofa/train_imgs_612.jpg b/domainlab/zdata/mixed_codec/sun/sofa/train_imgs_612.jpg new file mode 100644 index 000000000..55a3480d0 Binary files /dev/null and b/domainlab/zdata/mixed_codec/sun/sofa/train_imgs_612.jpg differ diff --git a/domainlab/zdata/mixed_codec/sun/vehicle/train_imgs_17.jpg b/domainlab/zdata/mixed_codec/sun/vehicle/train_imgs_17.jpg new file mode 100644 index 000000000..07f3213cc Binary files /dev/null and b/domainlab/zdata/mixed_codec/sun/vehicle/train_imgs_17.jpg differ diff --git a/domainlab/zdata/mixed_codec/sun/vehicle/train_imgs_19.jpg b/domainlab/zdata/mixed_codec/sun/vehicle/train_imgs_19.jpg new file mode 100644 index 000000000..33aba5e89 Binary files /dev/null and b/domainlab/zdata/mixed_codec/sun/vehicle/train_imgs_19.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/dog/pic_195.jpg b/domainlab/zdata/pacs_mini_10/art_painting/dog/pic_195.jpg new file mode 100644 index 000000000..40f008068 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/dog/pic_195.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/dog/pic_304.jpg b/domainlab/zdata/pacs_mini_10/art_painting/dog/pic_304.jpg new file mode 100644 index 000000000..5f558c11d Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/dog/pic_304.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/elephant/pic_026.jpg b/domainlab/zdata/pacs_mini_10/art_painting/elephant/pic_026.jpg new file mode 100644 index 000000000..2901d4715 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/elephant/pic_026.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/giraffe/pic_243.jpg b/domainlab/zdata/pacs_mini_10/art_painting/giraffe/pic_243.jpg new file mode 100644 index 000000000..2ffc182e8 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/giraffe/pic_243.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/guitar/pic_020.jpg b/domainlab/zdata/pacs_mini_10/art_painting/guitar/pic_020.jpg new file mode 100644 index 000000000..bd14528d6 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/guitar/pic_020.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/guitar/pic_182.jpg b/domainlab/zdata/pacs_mini_10/art_painting/guitar/pic_182.jpg new file mode 100644 index 000000000..b137ff1db Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/guitar/pic_182.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/horse/pic_142.jpg b/domainlab/zdata/pacs_mini_10/art_painting/horse/pic_142.jpg new file mode 100644 index 000000000..a5c00422d Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/horse/pic_142.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/person/pic_165.jpg b/domainlab/zdata/pacs_mini_10/art_painting/person/pic_165.jpg new file mode 100644 index 000000000..83803783b Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/person/pic_165.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/person/pic_199.jpg b/domainlab/zdata/pacs_mini_10/art_painting/person/pic_199.jpg new file mode 100644 index 000000000..0afd6b2a6 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/person/pic_199.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/art_painting/person/pic_497.jpg b/domainlab/zdata/pacs_mini_10/art_painting/person/pic_497.jpg new file mode 100644 index 000000000..9e72f4953 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/art_painting/person/pic_497.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_112.jpg b/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_112.jpg new file mode 100644 index 000000000..0ee2f1c05 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_112.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_137.jpg b/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_137.jpg new file mode 100644 index 000000000..6926b6aeb Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_137.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_219.jpg b/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_219.jpg new file mode 100644 index 000000000..ce2957c1b Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/dog/pic_219.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/elephant/pic_332.jpg b/domainlab/zdata/pacs_mini_10/cartoon/elephant/pic_332.jpg new file mode 100644 index 000000000..f6b164d62 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/elephant/pic_332.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/giraffe/pic_377.jpg b/domainlab/zdata/pacs_mini_10/cartoon/giraffe/pic_377.jpg new file mode 100644 index 000000000..c4eace676 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/giraffe/pic_377.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/giraffe/pic_382.jpg b/domainlab/zdata/pacs_mini_10/cartoon/giraffe/pic_382.jpg new file mode 100644 index 000000000..386b37ae0 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/giraffe/pic_382.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/horse/pic_064.jpg b/domainlab/zdata/pacs_mini_10/cartoon/horse/pic_064.jpg new file mode 100644 index 000000000..dec5f3f40 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/horse/pic_064.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/house/pic_040.jpg b/domainlab/zdata/pacs_mini_10/cartoon/house/pic_040.jpg new file mode 100644 index 000000000..8318b173d Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/house/pic_040.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/person/pic_111.jpg b/domainlab/zdata/pacs_mini_10/cartoon/person/pic_111.jpg new file mode 100644 index 000000000..9b364463b Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/person/pic_111.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/cartoon/person/pic_180.jpg b/domainlab/zdata/pacs_mini_10/cartoon/person/pic_180.jpg new file mode 100644 index 000000000..a22db07e7 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/cartoon/person/pic_180.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/main.sh b/domainlab/zdata/pacs_mini_10/main.sh new file mode 100644 index 000000000..8e44c8183 --- /dev/null +++ b/domainlab/zdata/pacs_mini_10/main.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# first argument is the file with pointers to image +# s +bash run_with_bash_copy_files_according2txt.sh ../pacs_split/art_painting_10.txt ~/Documents/dataset/PACS/raw . +bash run_with_bash_copy_files_according2txt.sh ../pacs_split/cartoon_10.txt ~/Documents/dataset/PACS/raw . +bash run_with_bash_copy_files_according2txt.sh ../pacs_split/photo_10.txt ~/Documents/dataset/PACS/raw . +bash run_with_bash_copy_files_according2txt.sh ../pacs_split/sketch_10.txt ~/Documents/dataset/PACS/raw . diff --git a/domainlab/zdata/pacs_mini_10/photo/dog/n02103406_1011.jpg b/domainlab/zdata/pacs_mini_10/photo/dog/n02103406_1011.jpg new file mode 100644 index 000000000..8859d6d21 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/dog/n02103406_1011.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/elephant/n02503517_6232.jpg b/domainlab/zdata/pacs_mini_10/photo/elephant/n02503517_6232.jpg new file mode 100644 index 000000000..06333ace2 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/elephant/n02503517_6232.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/guitar/n02676566_7830.jpg b/domainlab/zdata/pacs_mini_10/photo/guitar/n02676566_7830.jpg new file mode 100644 index 000000000..513f836b1 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/guitar/n02676566_7830.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/horse/105_0223.jpg b/domainlab/zdata/pacs_mini_10/photo/horse/105_0223.jpg new file mode 100644 index 000000000..6f8c61346 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/horse/105_0223.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/house/pic_046.jpg b/domainlab/zdata/pacs_mini_10/photo/house/pic_046.jpg new file mode 100644 index 000000000..fee8e964f Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/house/pic_046.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/house/pic_110.jpg b/domainlab/zdata/pacs_mini_10/photo/house/pic_110.jpg new file mode 100644 index 000000000..f7de2e500 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/house/pic_110.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/house/pic_146.jpg b/domainlab/zdata/pacs_mini_10/photo/house/pic_146.jpg new file mode 100644 index 000000000..2de68aedc Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/house/pic_146.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/house/pic_218.jpg b/domainlab/zdata/pacs_mini_10/photo/house/pic_218.jpg new file mode 100644 index 000000000..d7271783c Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/house/pic_218.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/person/253_0221.jpg b/domainlab/zdata/pacs_mini_10/photo/person/253_0221.jpg new file mode 100644 index 000000000..ba960df6a Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/person/253_0221.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/photo/person/253_0297.jpg b/domainlab/zdata/pacs_mini_10/photo/person/253_0297.jpg new file mode 100644 index 000000000..88b89ec7a Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/photo/person/253_0297.jpg differ diff --git a/domainlab/zdata/pacs_mini_10/run_with_bash_copy_files_according2txt.sh b/domainlab/zdata/pacs_mini_10/run_with_bash_copy_files_according2txt.sh new file mode 100644 index 000000000..695e46218 --- /dev/null +++ b/domainlab/zdata/pacs_mini_10/run_with_bash_copy_files_according2txt.sh @@ -0,0 +1,26 @@ +#!/bin/bash +input=$1 +path=$2 + +# test string array works +sentence="this is a story" +stringarray=($sentence) +echo "${stringarray[0]}" + +while IFS= read -r line +do + echo "$line" + stringarray=($line) + echo "${stringarray[0]}" + relativepath=${stringarray[0]} + fullpath="$path/$relativepath" + echo "fullpath is $fullpath" + newpath="$3/$relativepath" + echo "newpath is $newpath" + newpath2=`dirname "$newpath"` + echo "newpath2 is $newpath2" + mkdir -p "$newpath2" + cp "$fullpath" "$newpath2" + # cp "$fullpath" --parent "$3" + +done < "$input" diff --git a/domainlab/zdata/pacs_mini_10/sketch/dog/5302.png b/domainlab/zdata/pacs_mini_10/sketch/dog/5302.png new file mode 100644 index 000000000..3ec54e87b Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/dog/5302.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/dog/5317.png b/domainlab/zdata/pacs_mini_10/sketch/dog/5317.png new file mode 100644 index 000000000..8e6434ab4 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/dog/5317.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/dog/n02103406_3255-6.png b/domainlab/zdata/pacs_mini_10/sketch/dog/n02103406_3255-6.png new file mode 100644 index 000000000..2921bfe54 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/dog/n02103406_3255-6.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/elephant/5981.png b/domainlab/zdata/pacs_mini_10/sketch/elephant/5981.png new file mode 100644 index 000000000..22562d022 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/elephant/5981.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/elephant/n02503517_12688-4.png b/domainlab/zdata/pacs_mini_10/sketch/elephant/n02503517_12688-4.png new file mode 100644 index 000000000..2bdebdc11 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/elephant/n02503517_12688-4.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/giraffe/n02439033_13384-2.png b/domainlab/zdata/pacs_mini_10/sketch/giraffe/n02439033_13384-2.png new file mode 100644 index 000000000..81ac8d66e Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/giraffe/n02439033_13384-2.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/guitar/n02676566_8618-2.png b/domainlab/zdata/pacs_mini_10/sketch/guitar/n02676566_8618-2.png new file mode 100644 index 000000000..be920f071 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/guitar/n02676566_8618-2.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/guitar/n03467517_6423-3.png b/domainlab/zdata/pacs_mini_10/sketch/guitar/n03467517_6423-3.png new file mode 100644 index 000000000..7bfd45e84 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/guitar/n03467517_6423-3.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/horse/n02374451_779-1.png b/domainlab/zdata/pacs_mini_10/sketch/horse/n02374451_779-1.png new file mode 100644 index 000000000..1c09e0754 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/horse/n02374451_779-1.png differ diff --git a/domainlab/zdata/pacs_mini_10/sketch/house/8873.png b/domainlab/zdata/pacs_mini_10/sketch/house/8873.png new file mode 100644 index 000000000..6645def94 Binary files /dev/null and b/domainlab/zdata/pacs_mini_10/sketch/house/8873.png differ diff --git a/domainlab/zdata/pacs_split/art_painting_10.txt b/domainlab/zdata/pacs_split/art_painting_10.txt new file mode 100644 index 000000000..77f7627a2 --- /dev/null +++ b/domainlab/zdata/pacs_split/art_painting_10.txt @@ -0,0 +1,10 @@ +art_painting/person/pic_199.jpg 7 +art_painting/person/pic_497.jpg 7 +art_painting/guitar/pic_020.jpg 4 +art_painting/dog/pic_195.jpg 1 +art_painting/guitar/pic_182.jpg 4 +art_painting/giraffe/pic_243.jpg 3 +art_painting/elephant/pic_026.jpg 2 +art_painting/dog/pic_304.jpg 1 +art_painting/horse/pic_142.jpg 5 +art_painting/person/pic_165.jpg 7 diff --git a/domainlab/zdata/pacs_split/art_painting_100.txt b/domainlab/zdata/pacs_split/art_painting_100.txt new file mode 100644 index 000000000..7da95eda1 --- /dev/null +++ b/domainlab/zdata/pacs_split/art_painting_100.txt @@ -0,0 +1,100 @@ +art_painting/dog/pic_289.jpg 1 +art_painting/person/pic_460.jpg 7 +art_painting/horse/pic_073.jpg 5 +art_painting/horse/pic_108.jpg 5 +art_painting/dog/pic_324.jpg 1 +art_painting/elephant/pic_053.jpg 2 +art_painting/horse/pic_174.jpg 5 +art_painting/giraffe/pic_035.jpg 3 +art_painting/horse/pic_223.jpg 5 +art_painting/person/pic_387.jpg 7 +art_painting/dog/pic_196.jpg 1 +art_painting/horse/pic_171.jpg 5 +art_painting/person/pic_184.jpg 7 +art_painting/dog/pic_146.jpg 1 +art_painting/dog/pic_002.jpg 1 +art_painting/dog/pic_121.jpg 1 +art_painting/dog/pic_180.jpg 1 +art_painting/giraffe/pic_192.jpg 3 +art_painting/giraffe/pic_236.jpg 3 +art_painting/house/pic_306.jpg 6 +art_painting/person/pic_089.jpg 7 +art_painting/dog/pic_212.jpg 1 +art_painting/dog/pic_387.jpg 1 +art_painting/person/pic_214.jpg 7 +art_painting/elephant/pic_240.jpg 2 +art_painting/guitar/pic_064.jpg 4 +art_painting/elephant/pic_218.jpg 2 +art_painting/guitar/pic_011.jpg 4 +art_painting/horse/pic_151.jpg 5 +art_painting/house/pic_301.jpg 6 +art_painting/elephant/pic_193.jpg 2 +art_painting/dog/pic_117.jpg 1 +art_painting/person/pic_171.jpg 7 +art_painting/person/pic_143.jpg 7 +art_painting/house/pic_125.jpg 6 +art_painting/house/pic_044.jpg 6 +art_painting/dog/pic_077.jpg 1 +art_painting/person/pic_132.jpg 7 +art_painting/dog/pic_150.jpg 1 +art_painting/dog/pic_268.jpg 1 +art_painting/house/pic_207.jpg 6 +art_painting/guitar/pic_189.jpg 4 +art_painting/dog/pic_183.jpg 1 +art_painting/elephant/pic_164.jpg 2 +art_painting/guitar/pic_035.jpg 4 +art_painting/giraffe/pic_259.jpg 3 +art_painting/giraffe/pic_119.jpg 3 +art_painting/elephant/pic_098.jpg 2 +art_painting/horse/pic_160.jpg 5 +art_painting/giraffe/pic_204.jpg 3 +art_painting/horse/pic_196.jpg 5 +art_painting/giraffe/pic_046.jpg 3 +art_painting/dog/pic_245.jpg 1 +art_painting/horse/pic_083.jpg 5 +art_painting/house/pic_131.jpg 6 +art_painting/dog/pic_388.jpg 1 +art_painting/horse/pic_050.jpg 5 +art_painting/house/pic_171.jpg 6 +art_painting/elephant/pic_041.jpg 2 +art_painting/person/pic_108.jpg 7 +art_painting/guitar/pic_113.jpg 4 +art_painting/dog/pic_244.jpg 1 +art_painting/person/pic_111.jpg 7 +art_painting/horse/pic_081.jpg 5 +art_painting/dog/pic_186.jpg 1 +art_painting/dog/pic_258.jpg 1 +art_painting/house/pic_156.jpg 6 +art_painting/horse/pic_062.jpg 5 +art_painting/guitar/pic_085.jpg 4 +art_painting/dog/pic_090.jpg 1 +art_painting/person/pic_228.jpg 7 +art_painting/horse/pic_154.jpg 5 +art_painting/dog/pic_299.jpg 1 +art_painting/person/pic_510.jpg 7 +art_painting/person/pic_468.jpg 7 +art_painting/horse/pic_222.jpg 5 +art_painting/guitar/pic_104.jpg 4 +art_painting/giraffe/pic_015.jpg 3 +art_painting/person/pic_256.jpg 7 +art_painting/giraffe/pic_171.jpg 3 +art_painting/horse/pic_107.jpg 5 +art_painting/horse/pic_225.jpg 5 +art_painting/elephant/pic_102.jpg 2 +art_painting/guitar/pic_155.jpg 4 +art_painting/elephant/pic_144.jpg 2 +art_painting/giraffe/pic_058.jpg 3 +art_painting/person/pic_356.jpg 7 +art_painting/guitar/pic_136.jpg 4 +art_painting/person/pic_572.jpg 7 +art_painting/house/pic_104.jpg 6 +art_painting/elephant/pic_210.jpg 2 +art_painting/house/pic_346.jpg 6 +art_painting/dog/pic_246.jpg 1 +art_painting/dog/pic_024.jpg 1 +art_painting/elephant/pic_221.jpg 2 +art_painting/person/pic_145.jpg 7 +art_painting/person/pic_042.jpg 7 +art_painting/house/pic_116.jpg 6 +art_painting/house/pic_198.jpg 6 +art_painting/person/pic_342.jpg 7 diff --git a/domainlab/zdata/pacs_split/art_painting_crossval_kfold.txt b/domainlab/zdata/pacs_split/art_painting_crossval_kfold.txt new file mode 100644 index 000000000..61b3f44e1 --- /dev/null +++ b/domainlab/zdata/pacs_split/art_painting_crossval_kfold.txt @@ -0,0 +1,208 @@ +art_painting/dog/pic_225.jpg 0 +art_painting/dog/pic_248.jpg 1 +art_painting/dog/pic_306.jpg 1 +art_painting/dog/pic_241.jpg 1 +art_painting/dog/pic_219.jpg 1 +art_painting/dog/pic_252.jpg 1 +art_painting/dog/pic_309.jpg 1 +art_painting/dog/pic_255.jpg 1 +art_painting/dog/pic_310.jpg 1 +art_painting/dog/pic_247.jpg 1 +art_painting/dog/pic_236.jpg 1 +art_painting/dog/pic_242.jpg 1 +art_painting/dog/pic_257.jpg 1 +art_painting/dog/pic_314.jpg 1 +art_painting/dog/pic_317.jpg 1 +art_painting/dog/pic_315.jpg 1 +art_painting/dog/pic_248.jpg 1 +art_painting/dog/pic_250.jpg 1 +art_painting/dog/pic_282.jpg 1 +art_painting/dog/pic_260.jpg 1 +art_painting/dog/pic_316.jpg 1 +art_painting/dog/pic_305.jpg 1 +art_painting/dog/pic_300.jpg 1 +art_painting/dog/pic_365.jpg 1 +art_painting/dog/pic_296.jpg 1 +art_painting/dog/pic_301.jpg 1 +art_painting/dog/pic_298.jpg 1 +art_painting/dog/pic_291.jpg 1 +art_painting/dog/pic_313.jpg 1 +art_painting/dog/pic_311.jpg 1 +art_painting/dog/pic_312.jpg 1 +art_painting/dog/pic_308.jpg 1 +art_painting/dog/pic_329.jpg 1 +art_painting/dog/pic_322.jpg 1 +art_painting/dog/pic_323.jpg 1 +art_painting/dog/pic_330.jpg 1 +art_painting/dog/pic_371.jpg 1 +art_painting/dog/pic_339.jpg 1 +art_painting/elephant/pic_243.jpg 2 +art_painting/elephant/pic_154.jpg 2 +art_painting/elephant/pic_239.jpg 2 +art_painting/elephant/pic_156.jpg 2 +art_painting/elephant/pic_167.jpg 2 +art_painting/elephant/pic_168.jpg 2 +art_painting/elephant/pic_162.jpg 2 +art_painting/elephant/pic_161.jpg 2 +art_painting/elephant/pic_159.jpg 2 +art_painting/elephant/pic_160.jpg 2 +art_painting/elephant/pic_158.jpg 2 +art_painting/elephant/pic_157.jpg 2 +art_painting/elephant/pic_166.jpg 2 +art_painting/elephant/pic_171.jpg 2 +art_painting/elephant/pic_169.jpg 2 +art_painting/elephant/pic_170.jpg 2 +art_painting/elephant/pic_176.jpg 2 +art_painting/elephant/pic_175.jpg 2 +art_painting/elephant/pic_173.jpg 2 +art_painting/elephant/pic_172.jpg 2 +art_painting/elephant/pic_082.jpg 2 +art_painting/elephant/pic_081.jpg 2 +art_painting/elephant/pic_080.jpg 2 +art_painting/elephant/pic_078.jpg 2 +art_painting/elephant/pic_079.jpg 2 +art_painting/elephant/pic_093.jpg 2 +art_painting/giraffe/pic_134.jpg 3 +art_painting/giraffe/pic_129.jpg 3 +art_painting/giraffe/pic_127.jpg 3 +art_painting/giraffe/pic_151.jpg 3 +art_painting/giraffe/pic_131.jpg 3 +art_painting/giraffe/pic_158.jpg 3 +art_painting/giraffe/pic_144.jpg 3 +art_painting/giraffe/pic_238.jpg 3 +art_painting/giraffe/pic_222.jpg 3 +art_painting/giraffe/pic_185.jpg 3 +art_painting/giraffe/pic_160.jpg 3 +art_painting/giraffe/pic_155.jpg 3 +art_painting/giraffe/pic_209.jpg 3 +art_painting/giraffe/pic_228.jpg 3 +art_painting/giraffe/pic_169.jpg 3 +art_painting/giraffe/pic_198.jpg 3 +art_painting/giraffe/pic_145.jpg 3 +art_painting/giraffe/pic_273.jpg 3 +art_painting/giraffe/pic_303.jpg 3 +art_painting/giraffe/pic_284.jpg 3 +art_painting/giraffe/pic_302.jpg 3 +art_painting/giraffe/pic_286.jpg 3 +art_painting/giraffe/pic_287.jpg 3 +art_painting/giraffe/pic_301.jpg 3 +art_painting/giraffe/pic_295.jpg 3 +art_painting/giraffe/pic_296.jpg 3 +art_painting/giraffe/pic_311.jpg 3 +art_painting/giraffe/pic_309.jpg 3 +art_painting/giraffe/pic_310.jpg 3 +art_painting/guitar/pic_125.jpg 4 +art_painting/guitar/pic_124.jpg 4 +art_painting/guitar/pic_179.jpg 4 +art_painting/guitar/pic_147.jpg 4 +art_painting/guitar/pic_146.jpg 4 +art_painting/guitar/pic_183.jpg 4 +art_painting/guitar/pic_126.jpg 4 +art_painting/guitar/pic_172.jpg 4 +art_painting/guitar/pic_137.jpg 4 +art_painting/guitar/pic_180.jpg 4 +art_painting/guitar/pic_150.jpg 4 +art_painting/guitar/pic_176.jpg 4 +art_painting/guitar/pic_187.jpg 4 +art_painting/guitar/pic_186.jpg 4 +art_painting/guitar/pic_184.jpg 4 +art_painting/guitar/pic_174.jpg 4 +art_painting/guitar/pic_165.jpg 4 +art_painting/guitar/pic_161.jpg 4 +art_painting/guitar/pic_162.jpg 4 +art_painting/horse/pic_034.jpg 5 +art_painting/horse/pic_040.jpg 5 +art_painting/horse/pic_039.jpg 5 +art_painting/horse/pic_042.jpg 5 +art_painting/horse/pic_028.jpg 5 +art_painting/horse/pic_037.jpg 5 +art_painting/horse/pic_041.jpg 5 +art_painting/horse/pic_033.jpg 5 +art_painting/horse/pic_038.jpg 5 +art_painting/horse/pic_025.jpg 5 +art_painting/horse/pic_023.jpg 5 +art_painting/horse/pic_045.jpg 5 +art_painting/horse/pic_030.jpg 5 +art_painting/horse/pic_043.jpg 5 +art_painting/horse/pic_021.jpg 5 +art_painting/horse/pic_026.jpg 5 +art_painting/horse/pic_046.jpg 5 +art_painting/horse/pic_001.jpg 5 +art_painting/horse/pic_002.jpg 5 +art_painting/horse/pic_003.jpg 5 +art_painting/horse/pic_004.jpg 5 +art_painting/house/pic_313.jpg 6 +art_painting/house/pic_169.jpg 6 +art_painting/house/pic_168.jpg 6 +art_painting/house/pic_308.jpg 6 +art_painting/house/pic_167.jpg 6 +art_painting/house/pic_310.jpg 6 +art_painting/house/pic_314.jpg 6 +art_painting/house/pic_170.jpg 6 +art_painting/house/pic_316.jpg 6 +art_painting/house/pic_175.jpg 6 +art_painting/house/pic_173.jpg 6 +art_painting/house/pic_322.jpg 6 +art_painting/house/pic_321.jpg 6 +art_painting/house/pic_320.jpg 6 +art_painting/house/pic_178.jpg 6 +art_painting/house/pic_331.jpg 6 +art_painting/house/pic_001.jpg 6 +art_painting/house/pic_002.jpg 6 +art_painting/house/pic_003.jpg 6 +art_painting/house/pic_004.jpg 6 +art_painting/house/pic_005.jpg 6 +art_painting/house/pic_006.jpg 6 +art_painting/house/pic_007.jpg 6 +art_painting/house/pic_008.jpg 6 +art_painting/house/pic_009.jpg 6 +art_painting/house/pic_010.jpg 6 +art_painting/house/pic_011.jpg 6 +art_painting/house/pic_013.jpg 6 +art_painting/house/pic_015.jpg 6 +art_painting/house/pic_030.jpg 6 +art_painting/person/pic_280.jpg 7 +art_painting/person/pic_278.jpg 7 +art_painting/person/pic_277.jpg 7 +art_painting/person/pic_276.jpg 7 +art_painting/person/pic_275.jpg 7 +art_painting/person/pic_273.jpg 7 +art_painting/person/pic_284.jpg 7 +art_painting/person/pic_283.jpg 7 +art_painting/person/pic_281.jpg 7 +art_painting/person/pic_282.jpg 7 +art_painting/person/pic_285.jpg 7 +art_painting/person/pic_269.jpg 7 +art_painting/person/pic_297.jpg 7 +art_painting/person/pic_298.jpg 7 +art_painting/person/pic_296.jpg 7 +art_painting/person/pic_295.jpg 7 +art_painting/person/pic_134.jpg 7 +art_painting/person/pic_133.jpg 7 +art_painting/person/pic_135.jpg 7 +art_painting/person/pic_310.jpg 7 +art_painting/person/pic_141.jpg 7 +art_painting/person/pic_001.jpg 7 +art_painting/person/pic_002.jpg 7 +art_painting/person/pic_003.jpg 7 +art_painting/person/pic_004.jpg 7 +art_painting/person/pic_005.jpg 7 +art_painting/person/pic_048.jpg 7 +art_painting/person/pic_050.jpg 7 +art_painting/person/pic_052.jpg 7 +art_painting/person/pic_055.jpg 7 +art_painting/person/pic_056.jpg 7 +art_painting/person/pic_065.jpg 7 +art_painting/person/pic_331.jpg 7 +art_painting/person/pic_330.jpg 7 +art_painting/person/pic_176.jpg 7 +art_painting/person/pic_416.jpg 7 +art_painting/person/pic_420.jpg 7 +art_painting/person/pic_426.jpg 7 +art_painting/person/pic_424.jpg 7 +art_painting/person/pic_423.jpg 7 +art_painting/person/pic_421.jpg 7 +art_painting/person/pic_183.jpg 7 +art_painting/person/pic_428.jpg 7 +art_painting/person/pic_430.jpg 7 +art_painting/person/pic_429.jpg 7 diff --git a/domainlab/zdata/pacs_split/art_painting_test_kfold.txt b/domainlab/zdata/pacs_split/art_painting_test_kfold.txt new file mode 100644 index 000000000..9a5728738 --- /dev/null +++ b/domainlab/zdata/pacs_split/art_painting_test_kfold.txt @@ -0,0 +1,2048 @@ +art_painting/dog/pic_225.jpg 1 +art_painting/dog/pic_249.jpg 1 +art_painting/dog/pic_306.jpg 1 +art_painting/dog/pic_241.jpg 1 +art_painting/dog/pic_219.jpg 1 +art_painting/dog/pic_252.jpg 1 +art_painting/dog/pic_309.jpg 1 +art_painting/dog/pic_255.jpg 1 +art_painting/dog/pic_310.jpg 1 +art_painting/dog/pic_247.jpg 1 +art_painting/dog/pic_236.jpg 1 +art_painting/dog/pic_242.jpg 1 +art_painting/dog/pic_257.jpg 1 +art_painting/dog/pic_314.jpg 1 +art_painting/dog/pic_317.jpg 1 +art_painting/dog/pic_315.jpg 1 +art_painting/dog/pic_248.jpg 1 +art_painting/dog/pic_250.jpg 1 +art_painting/dog/pic_282.jpg 1 +art_painting/dog/pic_260.jpg 1 +art_painting/dog/pic_316.jpg 1 +art_painting/dog/pic_305.jpg 1 +art_painting/dog/pic_300.jpg 1 +art_painting/dog/pic_365.jpg 1 +art_painting/dog/pic_296.jpg 1 +art_painting/dog/pic_301.jpg 1 +art_painting/dog/pic_298.jpg 1 +art_painting/dog/pic_291.jpg 1 +art_painting/dog/pic_313.jpg 1 +art_painting/dog/pic_311.jpg 1 +art_painting/dog/pic_312.jpg 1 +art_painting/dog/pic_308.jpg 1 +art_painting/dog/pic_329.jpg 1 +art_painting/dog/pic_322.jpg 1 +art_painting/dog/pic_323.jpg 1 +art_painting/dog/pic_330.jpg 1 +art_painting/dog/pic_371.jpg 1 +art_painting/dog/pic_339.jpg 1 +art_painting/dog/pic_333.jpg 1 +art_painting/dog/pic_376.jpg 1 +art_painting/dog/pic_259.jpg 1 +art_painting/dog/pic_261.jpg 1 +art_painting/dog/pic_256.jpg 1 +art_painting/dog/pic_253.jpg 1 +art_painting/dog/pic_265.jpg 1 +art_painting/dog/pic_258.jpg 1 +art_painting/dog/pic_279.jpg 1 +art_painting/dog/pic_324.jpg 1 +art_painting/dog/pic_325.jpg 1 +art_painting/dog/pic_332.jpg 1 +art_painting/dog/pic_251.jpg 1 +art_painting/dog/pic_275.jpg 1 +art_painting/dog/pic_276.jpg 1 +art_painting/dog/pic_269.jpg 1 +art_painting/dog/pic_267.jpg 1 +art_painting/dog/pic_334.jpg 1 +art_painting/dog/pic_278.jpg 1 +art_painting/dog/pic_266.jpg 1 +art_painting/dog/pic_340.jpg 1 +art_painting/dog/pic_198.jpg 1 +art_painting/dog/pic_166.jpg 1 +art_painting/dog/pic_196.jpg 1 +art_painting/dog/pic_268.jpg 1 +art_painting/dog/pic_192.jpg 1 +art_painting/dog/pic_272.jpg 1 +art_painting/dog/pic_274.jpg 1 +art_painting/dog/pic_209.jpg 1 +art_painting/dog/pic_201.jpg 1 +art_painting/dog/pic_205.jpg 1 +art_painting/dog/pic_208.jpg 1 +art_painting/dog/pic_210.jpg 1 +art_painting/dog/pic_226.jpg 1 +art_painting/dog/pic_221.jpg 1 +art_painting/dog/pic_281.jpg 1 +art_painting/dog/pic_193.jpg 1 +art_painting/dog/pic_199.jpg 1 +art_painting/dog/pic_188.jpg 1 +art_painting/dog/pic_234.jpg 1 +art_painting/dog/pic_009.jpg 1 +art_painting/dog/pic_010.jpg 1 +art_painting/dog/pic_011.jpg 1 +art_painting/dog/pic_012.jpg 1 +art_painting/dog/pic_013.jpg 1 +art_painting/dog/pic_014.jpg 1 +art_painting/dog/pic_015.jpg 1 +art_painting/dog/pic_016.jpg 1 +art_painting/dog/pic_017.jpg 1 +art_painting/dog/pic_018.jpg 1 +art_painting/dog/pic_019.jpg 1 +art_painting/dog/pic_023.jpg 1 +art_painting/dog/pic_020.jpg 1 +art_painting/dog/pic_022.jpg 1 +art_painting/dog/pic_031.jpg 1 +art_painting/dog/pic_026.jpg 1 +art_painting/dog/pic_029.jpg 1 +art_painting/dog/pic_028.jpg 1 +art_painting/dog/pic_025.jpg 1 +art_painting/dog/pic_032.jpg 1 +art_painting/dog/pic_113.jpg 1 +art_painting/dog/pic_116.jpg 1 +art_painting/dog/pic_121.jpg 1 +art_painting/dog/pic_118.jpg 1 +art_painting/dog/pic_132.jpg 1 +art_painting/dog/pic_105.jpg 1 +art_painting/dog/pic_114.jpg 1 +art_painting/dog/pic_237.jpg 1 +art_painting/dog/pic_239.jpg 1 +art_painting/dog/pic_177.jpg 1 +art_painting/dog/pic_172.jpg 1 +art_painting/dog/pic_170.jpg 1 +art_painting/dog/pic_169.jpg 1 +art_painting/dog/pic_240.jpg 1 +art_painting/dog/pic_244.jpg 1 +art_painting/dog/pic_243.jpg 1 +art_painting/dog/pic_127.jpg 1 +art_painting/dog/pic_146.jpg 1 +art_painting/dog/pic_130.jpg 1 +art_painting/dog/pic_143.jpg 1 +art_painting/dog/pic_148.jpg 1 +art_painting/dog/pic_140.jpg 1 +art_painting/dog/pic_246.jpg 1 +art_painting/dog/pic_147.jpg 1 +art_painting/dog/pic_139.jpg 1 +art_painting/dog/pic_144.jpg 1 +art_painting/dog/pic_176.jpg 1 +art_painting/dog/pic_153.jpg 1 +art_painting/dog/pic_187.jpg 1 +art_painting/dog/pic_165.jpg 1 +art_painting/dog/pic_163.jpg 1 +art_painting/dog/pic_167.jpg 1 +art_painting/dog/pic_164.jpg 1 +art_painting/dog/pic_181.jpg 1 +art_painting/dog/pic_183.jpg 1 +art_painting/dog/pic_401.jpg 1 +art_painting/dog/pic_395.jpg 1 +art_painting/dog/pic_412.jpg 1 +art_painting/dog/pic_409.jpg 1 +art_painting/dog/pic_414.jpg 1 +art_painting/dog/pic_407.jpg 1 +art_painting/dog/pic_404.jpg 1 +art_painting/dog/pic_415.jpg 1 +art_painting/dog/pic_410.jpg 1 +art_painting/dog/pic_413.jpg 1 +art_painting/dog/pic_408.jpg 1 +art_painting/dog/pic_382.jpg 1 +art_painting/dog/pic_342.jpg 1 +art_painting/dog/pic_343.jpg 1 +art_painting/dog/pic_271.jpg 1 +art_painting/dog/pic_280.jpg 1 +art_painting/dog/pic_303.jpg 1 +art_painting/dog/pic_349.jpg 1 +art_painting/dog/pic_290.jpg 1 +art_painting/dog/pic_289.jpg 1 +art_painting/dog/pic_287.jpg 1 +art_painting/dog/pic_284.jpg 1 +art_painting/dog/pic_283.jpg 1 +art_painting/dog/pic_286.jpg 1 +art_painting/dog/pic_307.jpg 1 +art_painting/dog/pic_293.jpg 1 +art_painting/dog/pic_299.jpg 1 +art_painting/dog/pic_288.jpg 1 +art_painting/dog/pic_354.jpg 1 +art_painting/dog/pic_358.jpg 1 +art_painting/dog/pic_295.jpg 1 +art_painting/dog/pic_292.jpg 1 +art_painting/dog/pic_400.jpg 1 +art_painting/dog/pic_351.jpg 1 +art_painting/dog/pic_350.jpg 1 +art_painting/dog/pic_348.jpg 1 +art_painting/dog/pic_346.jpg 1 +art_painting/dog/pic_405.jpg 1 +art_painting/dog/pic_411.jpg 1 +art_painting/dog/pic_406.jpg 1 +art_painting/dog/pic_357.jpg 1 +art_painting/dog/pic_359.jpg 1 +art_painting/dog/pic_369.jpg 1 +art_painting/dog/pic_355.jpg 1 +art_painting/dog/pic_360.jpg 1 +art_painting/dog/pic_377.jpg 1 +art_painting/dog/pic_361.jpg 1 +art_painting/dog/pic_367.jpg 1 +art_painting/dog/pic_362.jpg 1 +art_painting/dog/pic_372.jpg 1 +art_painting/dog/pic_370.jpg 1 +art_painting/dog/pic_366.jpg 1 +art_painting/dog/pic_375.jpg 1 +art_painting/dog/pic_374.jpg 1 +art_painting/dog/pic_368.jpg 1 +art_painting/dog/pic_392.jpg 1 +art_painting/dog/pic_380.jpg 1 +art_painting/dog/pic_381.jpg 1 +art_painting/dog/pic_386.jpg 1 +art_painting/dog/pic_385.jpg 1 +art_painting/dog/pic_384.jpg 1 +art_painting/dog/pic_378.jpg 1 +art_painting/dog/pic_383.jpg 1 +art_painting/dog/pic_393.jpg 1 +art_painting/dog/pic_388.jpg 1 +art_painting/dog/pic_394.jpg 1 +art_painting/dog/pic_391.jpg 1 +art_painting/dog/pic_390.jpg 1 +art_painting/dog/pic_399.jpg 1 +art_painting/dog/pic_396.jpg 1 +art_painting/dog/pic_110.jpg 1 +art_painting/dog/pic_120.jpg 1 +art_painting/dog/pic_123.jpg 1 +art_painting/dog/pic_112.jpg 1 +art_painting/dog/pic_126.jpg 1 +art_painting/dog/pic_065.jpg 1 +art_painting/dog/pic_064.jpg 1 +art_painting/dog/pic_066.jpg 1 +art_painting/dog/pic_062.jpg 1 +art_painting/dog/pic_070.jpg 1 +art_painting/dog/pic_131.jpg 1 +art_painting/dog/pic_133.jpg 1 +art_painting/dog/pic_136.jpg 1 +art_painting/dog/pic_145.jpg 1 +art_painting/dog/pic_149.jpg 1 +art_painting/dog/pic_152.jpg 1 +art_painting/dog/pic_151.jpg 1 +art_painting/dog/pic_179.jpg 1 +art_painting/dog/pic_178.jpg 1 +art_painting/dog/pic_182.jpg 1 +art_painting/dog/pic_109.jpg 1 +art_painting/dog/pic_107.jpg 1 +art_painting/dog/pic_185.jpg 1 +art_painting/dog/pic_106.jpg 1 +art_painting/dog/pic_083.jpg 1 +art_painting/dog/pic_088.jpg 1 +art_painting/dog/pic_087.jpg 1 +art_painting/dog/pic_089.jpg 1 +art_painting/dog/pic_103.jpg 1 +art_painting/dog/pic_124.jpg 1 +art_painting/dog/pic_150.jpg 1 +art_painting/dog/pic_137.jpg 1 +art_painting/dog/pic_092.jpg 1 +art_painting/dog/pic_085.jpg 1 +art_painting/dog/pic_001.jpg 1 +art_painting/dog/pic_002.jpg 1 +art_painting/dog/pic_003.jpg 1 +art_painting/dog/pic_004.jpg 1 +art_painting/dog/pic_005.jpg 1 +art_painting/dog/pic_006.jpg 1 +art_painting/dog/pic_007.jpg 1 +art_painting/dog/pic_008.jpg 1 +art_painting/dog/pic_055.jpg 1 +art_painting/dog/pic_048.jpg 1 +art_painting/dog/pic_047.jpg 1 +art_painting/dog/pic_052.jpg 1 +art_painting/dog/pic_050.jpg 1 +art_painting/dog/pic_046.jpg 1 +art_painting/dog/pic_075.jpg 1 +art_painting/dog/pic_076.jpg 1 +art_painting/dog/pic_090.jpg 1 +art_painting/dog/pic_097.jpg 1 +art_painting/dog/pic_099.jpg 1 +art_painting/dog/pic_061.jpg 1 +art_painting/dog/pic_058.jpg 1 +art_painting/dog/pic_056.jpg 1 +art_painting/dog/pic_063.jpg 1 +art_painting/dog/pic_057.jpg 1 +art_painting/dog/pic_060.jpg 1 +art_painting/dog/pic_059.jpg 1 +art_painting/dog/pic_104.jpg 1 +art_painting/dog/pic_108.jpg 1 +art_painting/dog/pic_173.jpg 1 +art_painting/dog/pic_174.jpg 1 +art_painting/dog/pic_254.jpg 1 +art_painting/dog/pic_184.jpg 1 +art_painting/dog/pic_191.jpg 1 +art_painting/dog/pic_194.jpg 1 +art_painting/dog/pic_189.jpg 1 +art_painting/dog/pic_262.jpg 1 +art_painting/dog/pic_195.jpg 1 +art_painting/dog/pic_214.jpg 1 +art_painting/dog/pic_213.jpg 1 +art_painting/dog/pic_263.jpg 1 +art_painting/dog/pic_264.jpg 1 +art_painting/dog/pic_186.jpg 1 +art_painting/dog/pic_168.jpg 1 +art_painting/dog/pic_206.jpg 1 +art_painting/dog/pic_202.jpg 1 +art_painting/dog/pic_180.jpg 1 +art_painting/dog/pic_204.jpg 1 +art_painting/dog/pic_154.jpg 1 +art_painting/dog/pic_072.jpg 1 +art_painting/dog/pic_074.jpg 1 +art_painting/dog/pic_073.jpg 1 +art_painting/dog/pic_086.jpg 1 +art_painting/dog/pic_082.jpg 1 +art_painting/dog/pic_067.jpg 1 +art_painting/dog/pic_158.jpg 1 +art_painting/dog/pic_079.jpg 1 +art_painting/dog/pic_077.jpg 1 +art_painting/dog/pic_161.jpg 1 +art_painting/dog/pic_096.jpg 1 +art_painting/dog/pic_095.jpg 1 +art_painting/dog/pic_080.jpg 1 +art_painting/dog/pic_100.jpg 1 +art_painting/dog/pic_102.jpg 1 +art_painting/dog/pic_091.jpg 1 +art_painting/dog/pic_135.jpg 1 +art_painting/dog/pic_033.jpg 1 +art_painting/dog/pic_034.jpg 1 +art_painting/dog/pic_024.jpg 1 +art_painting/dog/pic_021.jpg 1 +art_painting/dog/pic_027.jpg 1 +art_painting/dog/pic_035.jpg 1 +art_painting/dog/pic_037.jpg 1 +art_painting/dog/pic_039.jpg 1 +art_painting/dog/pic_036.jpg 1 +art_painting/dog/pic_041.jpg 1 +art_painting/dog/pic_042.jpg 1 +art_painting/dog/pic_038.jpg 1 +art_painting/dog/pic_045.jpg 1 +art_painting/dog/pic_043.jpg 1 +art_painting/dog/pic_044.jpg 1 +art_painting/dog/pic_049.jpg 1 +art_painting/dog/pic_040.jpg 1 +art_painting/dog/pic_051.jpg 1 +art_painting/dog/pic_054.jpg 1 +art_painting/dog/pic_053.jpg 1 +art_painting/dog/pic_344.jpg 1 +art_painting/dog/pic_328.jpg 1 +art_painting/dog/pic_321.jpg 1 +art_painting/dog/pic_320.jpg 1 +art_painting/dog/pic_326.jpg 1 +art_painting/dog/pic_327.jpg 1 +art_painting/dog/pic_318.jpg 1 +art_painting/dog/pic_387.jpg 1 +art_painting/dog/pic_319.jpg 1 +art_painting/dog/pic_341.jpg 1 +art_painting/dog/pic_331.jpg 1 +art_painting/dog/pic_337.jpg 1 +art_painting/dog/pic_335.jpg 1 +art_painting/dog/pic_338.jpg 1 +art_painting/dog/pic_336.jpg 1 +art_painting/dog/pic_353.jpg 1 +art_painting/dog/pic_352.jpg 1 +art_painting/dog/pic_397.jpg 1 +art_painting/dog/pic_345.jpg 1 +art_painting/dog/pic_398.jpg 1 +art_painting/dog/pic_098.jpg 1 +art_painting/dog/pic_094.jpg 1 +art_painting/dog/pic_081.jpg 1 +art_painting/dog/pic_101.jpg 1 +art_painting/dog/pic_078.jpg 1 +art_painting/dog/pic_084.jpg 1 +art_painting/dog/pic_211.jpg 1 +art_painting/dog/pic_138.jpg 1 +art_painting/dog/pic_155.jpg 1 +art_painting/dog/pic_156.jpg 1 +art_painting/dog/pic_157.jpg 1 +art_painting/dog/pic_222.jpg 1 +art_painting/dog/pic_217.jpg 1 +art_painting/dog/pic_223.jpg 1 +art_painting/dog/pic_229.jpg 1 +art_painting/dog/pic_134.jpg 1 +art_painting/dog/pic_117.jpg 1 +art_painting/dog/pic_235.jpg 1 +art_painting/dog/pic_200.jpg 1 +art_painting/dog/pic_245.jpg 1 +art_painting/dog/pic_285.jpg 1 +art_painting/dog/pic_212.jpg 1 +art_painting/dog/pic_197.jpg 1 +art_painting/dog/pic_294.jpg 1 +art_painting/dog/pic_215.jpg 1 +art_painting/dog/pic_203.jpg 1 +art_painting/dog/pic_297.jpg 1 +art_painting/dog/pic_231.jpg 1 +art_painting/dog/pic_233.jpg 1 +art_painting/dog/pic_224.jpg 1 +art_painting/dog/pic_227.jpg 1 +art_painting/dog/pic_230.jpg 1 +art_painting/dog/pic_228.jpg 1 +art_painting/dog/pic_232.jpg 1 +art_painting/dog/pic_238.jpg 1 +art_painting/dog/pic_220.jpg 1 +art_painting/dog/pic_304.jpg 1 +art_painting/elephant/pic_243.jpg 2 +art_painting/elephant/pic_154.jpg 2 +art_painting/elephant/pic_239.jpg 2 +art_painting/elephant/pic_156.jpg 2 +art_painting/elephant/pic_167.jpg 2 +art_painting/elephant/pic_168.jpg 2 +art_painting/elephant/pic_162.jpg 2 +art_painting/elephant/pic_161.jpg 2 +art_painting/elephant/pic_159.jpg 2 +art_painting/elephant/pic_160.jpg 2 +art_painting/elephant/pic_158.jpg 2 +art_painting/elephant/pic_157.jpg 2 +art_painting/elephant/pic_166.jpg 2 +art_painting/elephant/pic_171.jpg 2 +art_painting/elephant/pic_169.jpg 2 +art_painting/elephant/pic_170.jpg 2 +art_painting/elephant/pic_176.jpg 2 +art_painting/elephant/pic_175.jpg 2 +art_painting/elephant/pic_173.jpg 2 +art_painting/elephant/pic_172.jpg 2 +art_painting/elephant/pic_082.jpg 2 +art_painting/elephant/pic_081.jpg 2 +art_painting/elephant/pic_080.jpg 2 +art_painting/elephant/pic_078.jpg 2 +art_painting/elephant/pic_079.jpg 2 +art_painting/elephant/pic_093.jpg 2 +art_painting/elephant/pic_085.jpg 2 +art_painting/elephant/pic_090.jpg 2 +art_painting/elephant/pic_089.jpg 2 +art_painting/elephant/pic_099.jpg 2 +art_painting/elephant/pic_111.jpg 2 +art_painting/elephant/pic_108.jpg 2 +art_painting/elephant/pic_114.jpg 2 +art_painting/elephant/pic_116.jpg 2 +art_painting/elephant/pic_123.jpg 2 +art_painting/elephant/pic_133.jpg 2 +art_painting/elephant/pic_131.jpg 2 +art_painting/elephant/pic_122.jpg 2 +art_painting/elephant/pic_113.jpg 2 +art_painting/elephant/pic_115.jpg 2 +art_painting/elephant/pic_112.jpg 2 +art_painting/elephant/pic_251.jpg 2 +art_painting/elephant/pic_250.jpg 2 +art_painting/elephant/pic_242.jpg 2 +art_painting/elephant/pic_246.jpg 2 +art_painting/elephant/pic_257.jpg 2 +art_painting/elephant/pic_249.jpg 2 +art_painting/elephant/pic_261.jpg 2 +art_painting/elephant/pic_260.jpg 2 +art_painting/elephant/pic_259.jpg 2 +art_painting/elephant/pic_039.jpg 2 +art_painting/elephant/pic_033.jpg 2 +art_painting/elephant/pic_041.jpg 2 +art_painting/elephant/pic_049.jpg 2 +art_painting/elephant/pic_048.jpg 2 +art_painting/elephant/pic_030.jpg 2 +art_painting/elephant/pic_026.jpg 2 +art_painting/elephant/pic_052.jpg 2 +art_painting/elephant/pic_053.jpg 2 +art_painting/elephant/pic_050.jpg 2 +art_painting/elephant/pic_054.jpg 2 +art_painting/elephant/pic_058.jpg 2 +art_painting/elephant/pic_056.jpg 2 +art_painting/elephant/pic_057.jpg 2 +art_painting/elephant/pic_055.jpg 2 +art_painting/elephant/pic_059.jpg 2 +art_painting/elephant/pic_060.jpg 2 +art_painting/elephant/pic_065.jpg 2 +art_painting/elephant/pic_063.jpg 2 +art_painting/elephant/pic_064.jpg 2 +art_painting/elephant/pic_061.jpg 2 +art_painting/elephant/pic_193.jpg 2 +art_painting/elephant/pic_192.jpg 2 +art_painting/elephant/pic_198.jpg 2 +art_painting/elephant/pic_201.jpg 2 +art_painting/elephant/pic_199.jpg 2 +art_painting/elephant/pic_212.jpg 2 +art_painting/elephant/pic_211.jpg 2 +art_painting/elephant/pic_210.jpg 2 +art_painting/elephant/pic_209.jpg 2 +art_painting/elephant/pic_208.jpg 2 +art_painting/elephant/pic_206.jpg 2 +art_painting/elephant/pic_207.jpg 2 +art_painting/elephant/pic_205.jpg 2 +art_painting/elephant/pic_203.jpg 2 +art_painting/elephant/pic_204.jpg 2 +art_painting/elephant/pic_222.jpg 2 +art_painting/elephant/pic_221.jpg 2 +art_painting/elephant/pic_218.jpg 2 +art_painting/elephant/pic_215.jpg 2 +art_painting/elephant/pic_213.jpg 2 +art_painting/elephant/pic_035.jpg 2 +art_painting/elephant/pic_036.jpg 2 +art_painting/elephant/pic_031.jpg 2 +art_painting/elephant/pic_034.jpg 2 +art_painting/elephant/pic_027.jpg 2 +art_painting/elephant/pic_040.jpg 2 +art_painting/elephant/pic_044.jpg 2 +art_painting/elephant/pic_043.jpg 2 +art_painting/elephant/pic_029.jpg 2 +art_painting/elephant/pic_023.jpg 2 +art_painting/elephant/pic_037.jpg 2 +art_painting/elephant/pic_045.jpg 2 +art_painting/elephant/pic_024.jpg 2 +art_painting/elephant/pic_046.jpg 2 +art_painting/elephant/pic_022.jpg 2 +art_painting/elephant/pic_047.jpg 2 +art_painting/elephant/pic_025.jpg 2 +art_painting/elephant/pic_021.jpg 2 +art_painting/elephant/pic_020.jpg 2 +art_painting/elephant/pic_174.jpg 2 +art_painting/elephant/pic_182.jpg 2 +art_painting/elephant/pic_181.jpg 2 +art_painting/elephant/pic_180.jpg 2 +art_painting/elephant/pic_178.jpg 2 +art_painting/elephant/pic_177.jpg 2 +art_painting/elephant/pic_188.jpg 2 +art_painting/elephant/pic_187.jpg 2 +art_painting/elephant/pic_185.jpg 2 +art_painting/elephant/pic_186.jpg 2 +art_painting/elephant/pic_184.jpg 2 +art_painting/elephant/pic_183.jpg 2 +art_painting/elephant/pic_191.jpg 2 +art_painting/elephant/pic_190.jpg 2 +art_painting/elephant/pic_189.jpg 2 +art_painting/elephant/pic_202.jpg 2 +art_painting/elephant/pic_200.jpg 2 +art_painting/elephant/pic_196.jpg 2 +art_painting/elephant/pic_197.jpg 2 +art_painting/elephant/pic_194.jpg 2 +art_painting/elephant/pic_195.jpg 2 +art_painting/elephant/pic_110.jpg 2 +art_painting/elephant/pic_106.jpg 2 +art_painting/elephant/pic_105.jpg 2 +art_painting/elephant/pic_102.jpg 2 +art_painting/elephant/pic_101.jpg 2 +art_painting/elephant/pic_100.jpg 2 +art_painting/elephant/pic_097.jpg 2 +art_painting/elephant/pic_095.jpg 2 +art_painting/elephant/pic_096.jpg 2 +art_painting/elephant/pic_127.jpg 2 +art_painting/elephant/pic_150.jpg 2 +art_painting/elephant/pic_130.jpg 2 +art_painting/elephant/pic_119.jpg 2 +art_painting/elephant/pic_109.jpg 2 +art_painting/elephant/pic_104.jpg 2 +art_painting/elephant/pic_129.jpg 2 +art_painting/elephant/pic_128.jpg 2 +art_painting/elephant/pic_103.jpg 2 +art_painting/elephant/pic_098.jpg 2 +art_painting/elephant/pic_214.jpg 2 +art_painting/elephant/pic_217.jpg 2 +art_painting/elephant/pic_232.jpg 2 +art_painting/elephant/pic_231.jpg 2 +art_painting/elephant/pic_230.jpg 2 +art_painting/elephant/pic_229.jpg 2 +art_painting/elephant/pic_226.jpg 2 +art_painting/elephant/pic_224.jpg 2 +art_painting/elephant/pic_225.jpg 2 +art_painting/elephant/pic_223.jpg 2 +art_painting/elephant/pic_227.jpg 2 +art_painting/elephant/pic_228.jpg 2 +art_painting/elephant/pic_235.jpg 2 +art_painting/elephant/pic_236.jpg 2 +art_painting/elephant/pic_234.jpg 2 +art_painting/elephant/pic_241.jpg 2 +art_painting/elephant/pic_258.jpg 2 +art_painting/elephant/pic_256.jpg 2 +art_painting/elephant/pic_254.jpg 2 +art_painting/elephant/pic_255.jpg 2 +art_painting/elephant/pic_253.jpg 2 +art_painting/elephant/pic_004.jpg 2 +art_painting/elephant/pic_005.jpg 2 +art_painting/elephant/pic_006.jpg 2 +art_painting/elephant/pic_007.jpg 2 +art_painting/elephant/pic_008.jpg 2 +art_painting/elephant/pic_009.jpg 2 +art_painting/elephant/pic_010.jpg 2 +art_painting/elephant/pic_011.jpg 2 +art_painting/elephant/pic_012.jpg 2 +art_painting/elephant/pic_014.jpg 2 +art_painting/elephant/pic_015.jpg 2 +art_painting/elephant/pic_016.jpg 2 +art_painting/elephant/pic_017.jpg 2 +art_painting/elephant/pic_018.jpg 2 +art_painting/elephant/pic_019.jpg 2 +art_painting/elephant/pic_051.jpg 2 +art_painting/elephant/pic_042.jpg 2 +art_painting/elephant/pic_028.jpg 2 +art_painting/elephant/pic_032.jpg 2 +art_painting/elephant/pic_001.jpg 2 +art_painting/elephant/pic_002.jpg 2 +art_painting/elephant/pic_003.jpg 2 +art_painting/elephant/pic_107.jpg 2 +art_painting/elephant/pic_117.jpg 2 +art_painting/elephant/pic_120.jpg 2 +art_painting/elephant/pic_118.jpg 2 +art_painting/elephant/pic_121.jpg 2 +art_painting/elephant/pic_125.jpg 2 +art_painting/elephant/pic_124.jpg 2 +art_painting/elephant/pic_126.jpg 2 +art_painting/elephant/pic_132.jpg 2 +art_painting/elephant/pic_151.jpg 2 +art_painting/elephant/pic_138.jpg 2 +art_painting/elephant/pic_139.jpg 2 +art_painting/elephant/pic_136.jpg 2 +art_painting/elephant/pic_137.jpg 2 +art_painting/elephant/pic_179.jpg 2 +art_painting/elephant/pic_134.jpg 2 +art_painting/elephant/pic_164.jpg 2 +art_painting/elephant/pic_163.jpg 2 +art_painting/elephant/pic_135.jpg 2 +art_painting/elephant/pic_165.jpg 2 +art_painting/elephant/pic_219.jpg 2 +art_painting/elephant/pic_062.jpg 2 +art_painting/elephant/pic_066.jpg 2 +art_painting/elephant/pic_067.jpg 2 +art_painting/elephant/pic_068.jpg 2 +art_painting/elephant/pic_069.jpg 2 +art_painting/elephant/pic_070.jpg 2 +art_painting/elephant/pic_071.jpg 2 +art_painting/elephant/pic_072.jpg 2 +art_painting/elephant/pic_073.jpg 2 +art_painting/elephant/pic_074.jpg 2 +art_painting/elephant/pic_075.jpg 2 +art_painting/elephant/pic_076.jpg 2 +art_painting/elephant/pic_077.jpg 2 +art_painting/elephant/pic_094.jpg 2 +art_painting/elephant/pic_092.jpg 2 +art_painting/elephant/pic_091.jpg 2 +art_painting/elephant/pic_088.jpg 2 +art_painting/elephant/pic_087.jpg 2 +art_painting/elephant/pic_086.jpg 2 +art_painting/elephant/pic_084.jpg 2 +art_painting/elephant/pic_083.jpg 2 +art_painting/elephant/pic_146.jpg 2 +art_painting/elephant/pic_142.jpg 2 +art_painting/elephant/pic_144.jpg 2 +art_painting/elephant/pic_143.jpg 2 +art_painting/elephant/pic_140.jpg 2 +art_painting/elephant/pic_141.jpg 2 +art_painting/elephant/pic_145.jpg 2 +art_painting/elephant/pic_149.jpg 2 +art_painting/elephant/pic_233.jpg 2 +art_painting/elephant/pic_148.jpg 2 +art_painting/elephant/pic_147.jpg 2 +art_painting/elephant/pic_220.jpg 2 +art_painting/elephant/pic_153.jpg 2 +art_painting/elephant/pic_237.jpg 2 +art_painting/elephant/pic_152.jpg 2 +art_painting/elephant/pic_238.jpg 2 +art_painting/elephant/pic_155.jpg 2 +art_painting/elephant/pic_252.jpg 2 +art_painting/elephant/pic_244.jpg 2 +art_painting/elephant/pic_240.jpg 2 +art_painting/giraffe/pic_134.jpg 3 +art_painting/giraffe/pic_129.jpg 3 +art_painting/giraffe/pic_127.jpg 3 +art_painting/giraffe/pic_151.jpg 3 +art_painting/giraffe/pic_131.jpg 3 +art_painting/giraffe/pic_158.jpg 3 +art_painting/giraffe/pic_144.jpg 3 +art_painting/giraffe/pic_238.jpg 3 +art_painting/giraffe/pic_222.jpg 3 +art_painting/giraffe/pic_185.jpg 3 +art_painting/giraffe/pic_160.jpg 3 +art_painting/giraffe/pic_155.jpg 3 +art_painting/giraffe/pic_209.jpg 3 +art_painting/giraffe/pic_228.jpg 3 +art_painting/giraffe/pic_169.jpg 3 +art_painting/giraffe/pic_198.jpg 3 +art_painting/giraffe/pic_145.jpg 3 +art_painting/giraffe/pic_273.jpg 3 +art_painting/giraffe/pic_303.jpg 3 +art_painting/giraffe/pic_284.jpg 3 +art_painting/giraffe/pic_302.jpg 3 +art_painting/giraffe/pic_286.jpg 3 +art_painting/giraffe/pic_287.jpg 3 +art_painting/giraffe/pic_301.jpg 3 +art_painting/giraffe/pic_295.jpg 3 +art_painting/giraffe/pic_296.jpg 3 +art_painting/giraffe/pic_311.jpg 3 +art_painting/giraffe/pic_309.jpg 3 +art_painting/giraffe/pic_310.jpg 3 +art_painting/giraffe/pic_308.jpg 3 +art_painting/giraffe/pic_307.jpg 3 +art_painting/giraffe/pic_276.jpg 3 +art_painting/giraffe/pic_298.jpg 3 +art_painting/giraffe/pic_244.jpg 3 +art_painting/giraffe/pic_242.jpg 3 +art_painting/giraffe/pic_240.jpg 3 +art_painting/giraffe/pic_234.jpg 3 +art_painting/giraffe/pic_206.jpg 3 +art_painting/giraffe/pic_204.jpg 3 +art_painting/giraffe/pic_193.jpg 3 +art_painting/giraffe/pic_190.jpg 3 +art_painting/giraffe/pic_188.jpg 3 +art_painting/giraffe/pic_186.jpg 3 +art_painting/giraffe/pic_280.jpg 3 +art_painting/giraffe/pic_177.jpg 3 +art_painting/giraffe/pic_264.jpg 3 +art_painting/giraffe/pic_263.jpg 3 +art_painting/giraffe/pic_282.jpg 3 +art_painting/giraffe/pic_077.jpg 3 +art_painting/giraffe/pic_075.jpg 3 +art_painting/giraffe/pic_083.jpg 3 +art_painting/giraffe/pic_090.jpg 3 +art_painting/giraffe/pic_089.jpg 3 +art_painting/giraffe/pic_088.jpg 3 +art_painting/giraffe/pic_087.jpg 3 +art_painting/giraffe/pic_086.jpg 3 +art_painting/giraffe/pic_085.jpg 3 +art_painting/giraffe/pic_084.jpg 3 +art_painting/giraffe/pic_092.jpg 3 +art_painting/giraffe/pic_091.jpg 3 +art_painting/giraffe/pic_097.jpg 3 +art_painting/giraffe/pic_096.jpg 3 +art_painting/giraffe/pic_095.jpg 3 +art_painting/giraffe/pic_093.jpg 3 +art_painting/giraffe/pic_094.jpg 3 +art_painting/giraffe/pic_100.jpg 3 +art_painting/giraffe/pic_107.jpg 3 +art_painting/giraffe/pic_106.jpg 3 +art_painting/giraffe/pic_247.jpg 3 +art_painting/giraffe/pic_252.jpg 3 +art_painting/giraffe/pic_266.jpg 3 +art_painting/giraffe/pic_246.jpg 3 +art_painting/giraffe/pic_241.jpg 3 +art_painting/giraffe/pic_248.jpg 3 +art_painting/giraffe/pic_271.jpg 3 +art_painting/giraffe/pic_283.jpg 3 +art_painting/giraffe/pic_258.jpg 3 +art_painting/giraffe/pic_279.jpg 3 +art_painting/giraffe/pic_297.jpg 3 +art_painting/giraffe/pic_300.jpg 3 +art_painting/giraffe/pic_257.jpg 3 +art_painting/giraffe/pic_249.jpg 3 +art_painting/giraffe/pic_254.jpg 3 +art_painting/giraffe/pic_253.jpg 3 +art_painting/giraffe/pic_245.jpg 3 +art_painting/giraffe/pic_236.jpg 3 +art_painting/giraffe/pic_164.jpg 3 +art_painting/giraffe/pic_166.jpg 3 +art_painting/giraffe/pic_200.jpg 3 +art_painting/giraffe/pic_147.jpg 3 +art_painting/giraffe/pic_210.jpg 3 +art_painting/giraffe/pic_170.jpg 3 +art_painting/giraffe/pic_168.jpg 3 +art_painting/giraffe/pic_223.jpg 3 +art_painting/giraffe/pic_213.jpg 3 +art_painting/giraffe/pic_207.jpg 3 +art_painting/giraffe/pic_171.jpg 3 +art_painting/giraffe/pic_232.jpg 3 +art_painting/giraffe/pic_211.jpg 3 +art_painting/giraffe/pic_221.jpg 3 +art_painting/giraffe/pic_230.jpg 3 +art_painting/giraffe/pic_235.jpg 3 +art_painting/giraffe/pic_212.jpg 3 +art_painting/giraffe/pic_231.jpg 3 +art_painting/giraffe/pic_021.jpg 3 +art_painting/giraffe/pic_033.jpg 3 +art_painting/giraffe/pic_050.jpg 3 +art_painting/giraffe/pic_046.jpg 3 +art_painting/giraffe/pic_045.jpg 3 +art_painting/giraffe/pic_030.jpg 3 +art_painting/giraffe/pic_037.jpg 3 +art_painting/giraffe/pic_024.jpg 3 +art_painting/giraffe/pic_042.jpg 3 +art_painting/giraffe/pic_028.jpg 3 +art_painting/giraffe/pic_051.jpg 3 +art_painting/giraffe/pic_025.jpg 3 +art_painting/giraffe/pic_043.jpg 3 +art_painting/giraffe/pic_052.jpg 3 +art_painting/giraffe/pic_049.jpg 3 +art_painting/giraffe/pic_044.jpg 3 +art_painting/giraffe/pic_023.jpg 3 +art_painting/giraffe/pic_053.jpg 3 +art_painting/giraffe/pic_056.jpg 3 +art_painting/giraffe/pic_068.jpg 3 +art_painting/giraffe/pic_063.jpg 3 +art_painting/giraffe/pic_182.jpg 3 +art_painting/giraffe/pic_173.jpg 3 +art_painting/giraffe/pic_165.jpg 3 +art_painting/giraffe/pic_154.jpg 3 +art_painting/giraffe/pic_138.jpg 3 +art_painting/giraffe/pic_137.jpg 3 +art_painting/giraffe/pic_136.jpg 3 +art_painting/giraffe/pic_062.jpg 3 +art_painting/giraffe/pic_061.jpg 3 +art_painting/giraffe/pic_059.jpg 3 +art_painting/giraffe/pic_060.jpg 3 +art_painting/giraffe/pic_058.jpg 3 +art_painting/giraffe/pic_057.jpg 3 +art_painting/giraffe/pic_069.jpg 3 +art_painting/giraffe/pic_066.jpg 3 +art_painting/giraffe/pic_065.jpg 3 +art_painting/giraffe/pic_070.jpg 3 +art_painting/giraffe/pic_072.jpg 3 +art_painting/giraffe/pic_071.jpg 3 +art_painting/giraffe/pic_074.jpg 3 +art_painting/giraffe/pic_073.jpg 3 +art_painting/giraffe/pic_081.jpg 3 +art_painting/giraffe/pic_082.jpg 3 +art_painting/giraffe/pic_080.jpg 3 +art_painting/giraffe/pic_078.jpg 3 +art_painting/giraffe/pic_079.jpg 3 +art_painting/giraffe/pic_001.jpg 3 +art_painting/giraffe/pic_002.jpg 3 +art_painting/giraffe/pic_003.jpg 3 +art_painting/giraffe/pic_004.jpg 3 +art_painting/giraffe/pic_005.jpg 3 +art_painting/giraffe/pic_007.jpg 3 +art_painting/giraffe/pic_008.jpg 3 +art_painting/giraffe/pic_009.jpg 3 +art_painting/giraffe/pic_010.jpg 3 +art_painting/giraffe/pic_011.jpg 3 +art_painting/giraffe/pic_012.jpg 3 +art_painting/giraffe/pic_013.jpg 3 +art_painting/giraffe/pic_014.jpg 3 +art_painting/giraffe/pic_015.jpg 3 +art_painting/giraffe/pic_016.jpg 3 +art_painting/giraffe/pic_140.jpg 3 +art_painting/giraffe/pic_150.jpg 3 +art_painting/giraffe/pic_159.jpg 3 +art_painting/giraffe/pic_135.jpg 3 +art_painting/giraffe/pic_224.jpg 3 +art_painting/giraffe/pic_153.jpg 3 +art_painting/giraffe/pic_227.jpg 3 +art_painting/giraffe/pic_226.jpg 3 +art_painting/giraffe/pic_162.jpg 3 +art_painting/giraffe/pic_175.jpg 3 +art_painting/giraffe/pic_225.jpg 3 +art_painting/giraffe/pic_229.jpg 3 +art_painting/giraffe/pic_167.jpg 3 +art_painting/giraffe/pic_174.jpg 3 +art_painting/giraffe/pic_161.jpg 3 +art_painting/giraffe/pic_184.jpg 3 +art_painting/giraffe/pic_141.jpg 3 +art_painting/giraffe/pic_201.jpg 3 +art_painting/giraffe/pic_237.jpg 3 +art_painting/giraffe/pic_163.jpg 3 +art_painting/giraffe/pic_133.jpg 3 +art_painting/giraffe/pic_132.jpg 3 +art_painting/giraffe/pic_130.jpg 3 +art_painting/giraffe/pic_125.jpg 3 +art_painting/giraffe/pic_123.jpg 3 +art_painting/giraffe/pic_121.jpg 3 +art_painting/giraffe/pic_122.jpg 3 +art_painting/giraffe/pic_119.jpg 3 +art_painting/giraffe/pic_120.jpg 3 +art_painting/giraffe/pic_118.jpg 3 +art_painting/giraffe/pic_208.jpg 3 +art_painting/giraffe/pic_217.jpg 3 +art_painting/giraffe/pic_172.jpg 3 +art_painting/giraffe/pic_157.jpg 3 +art_painting/giraffe/pic_152.jpg 3 +art_painting/giraffe/pic_143.jpg 3 +art_painting/giraffe/pic_176.jpg 3 +art_painting/giraffe/pic_146.jpg 3 +art_painting/giraffe/pic_139.jpg 3 +art_painting/giraffe/pic_142.jpg 3 +art_painting/giraffe/pic_105.jpg 3 +art_painting/giraffe/pic_104.jpg 3 +art_painting/giraffe/pic_102.jpg 3 +art_painting/giraffe/pic_101.jpg 3 +art_painting/giraffe/pic_099.jpg 3 +art_painting/giraffe/pic_098.jpg 3 +art_painting/giraffe/pic_103.jpg 3 +art_painting/giraffe/pic_115.jpg 3 +art_painting/giraffe/pic_117.jpg 3 +art_painting/giraffe/pic_116.jpg 3 +art_painting/giraffe/pic_110.jpg 3 +art_painting/giraffe/pic_113.jpg 3 +art_painting/giraffe/pic_111.jpg 3 +art_painting/giraffe/pic_112.jpg 3 +art_painting/giraffe/pic_109.jpg 3 +art_painting/giraffe/pic_108.jpg 3 +art_painting/giraffe/pic_114.jpg 3 +art_painting/giraffe/pic_126.jpg 3 +art_painting/giraffe/pic_128.jpg 3 +art_painting/giraffe/pic_218.jpg 3 +art_painting/giraffe/pic_178.jpg 3 +art_painting/giraffe/pic_191.jpg 3 +art_painting/giraffe/pic_285.jpg 3 +art_painting/giraffe/pic_270.jpg 3 +art_painting/giraffe/pic_267.jpg 3 +art_painting/giraffe/pic_288.jpg 3 +art_painting/giraffe/pic_261.jpg 3 +art_painting/giraffe/pic_305.jpg 3 +art_painting/giraffe/pic_274.jpg 3 +art_painting/giraffe/pic_251.jpg 3 +art_painting/giraffe/pic_291.jpg 3 +art_painting/giraffe/pic_259.jpg 3 +art_painting/giraffe/pic_262.jpg 3 +art_painting/giraffe/pic_304.jpg 3 +art_painting/giraffe/pic_268.jpg 3 +art_painting/giraffe/pic_256.jpg 3 +art_painting/giraffe/pic_281.jpg 3 +art_painting/giraffe/pic_292.jpg 3 +art_painting/giraffe/pic_293.jpg 3 +art_painting/giraffe/pic_277.jpg 3 +art_painting/giraffe/pic_017.jpg 3 +art_painting/giraffe/pic_018.jpg 3 +art_painting/giraffe/pic_019.jpg 3 +art_painting/giraffe/pic_022.jpg 3 +art_painting/giraffe/pic_027.jpg 3 +art_painting/giraffe/pic_034.jpg 3 +art_painting/giraffe/pic_035.jpg 3 +art_painting/giraffe/pic_029.jpg 3 +art_painting/giraffe/pic_055.jpg 3 +art_painting/giraffe/pic_054.jpg 3 +art_painting/giraffe/pic_048.jpg 3 +art_painting/giraffe/pic_047.jpg 3 +art_painting/giraffe/pic_031.jpg 3 +art_painting/giraffe/pic_032.jpg 3 +art_painting/giraffe/pic_041.jpg 3 +art_painting/giraffe/pic_036.jpg 3 +art_painting/giraffe/pic_040.jpg 3 +art_painting/giraffe/pic_038.jpg 3 +art_painting/giraffe/pic_039.jpg 3 +art_painting/giraffe/pic_020.jpg 3 +art_painting/giraffe/pic_026.jpg 3 +art_painting/giraffe/pic_243.jpg 3 +art_painting/giraffe/pic_278.jpg 3 +art_painting/giraffe/pic_272.jpg 3 +art_painting/giraffe/pic_306.jpg 3 +art_painting/giraffe/pic_290.jpg 3 +art_painting/giraffe/pic_265.jpg 3 +art_painting/giraffe/pic_255.jpg 3 +art_painting/giraffe/pic_194.jpg 3 +art_painting/giraffe/pic_216.jpg 3 +art_painting/giraffe/pic_215.jpg 3 +art_painting/giraffe/pic_233.jpg 3 +art_painting/giraffe/pic_203.jpg 3 +art_painting/giraffe/pic_192.jpg 3 +art_painting/giraffe/pic_214.jpg 3 +art_painting/giraffe/pic_239.jpg 3 +art_painting/giraffe/pic_205.jpg 3 +art_painting/giraffe/pic_180.jpg 3 +art_painting/giraffe/pic_195.jpg 3 +art_painting/guitar/pic_125.jpg 4 +art_painting/guitar/pic_124.jpg 4 +art_painting/guitar/pic_179.jpg 4 +art_painting/guitar/pic_147.jpg 4 +art_painting/guitar/pic_146.jpg 4 +art_painting/guitar/pic_183.jpg 4 +art_painting/guitar/pic_126.jpg 4 +art_painting/guitar/pic_172.jpg 4 +art_painting/guitar/pic_137.jpg 4 +art_painting/guitar/pic_180.jpg 4 +art_painting/guitar/pic_150.jpg 4 +art_painting/guitar/pic_176.jpg 4 +art_painting/guitar/pic_187.jpg 4 +art_painting/guitar/pic_186.jpg 4 +art_painting/guitar/pic_184.jpg 4 +art_painting/guitar/pic_174.jpg 4 +art_painting/guitar/pic_165.jpg 4 +art_painting/guitar/pic_161.jpg 4 +art_painting/guitar/pic_162.jpg 4 +art_painting/guitar/pic_055.jpg 4 +art_painting/guitar/pic_059.jpg 4 +art_painting/guitar/pic_061.jpg 4 +art_painting/guitar/pic_060.jpg 4 +art_painting/guitar/pic_062.jpg 4 +art_painting/guitar/pic_063.jpg 4 +art_painting/guitar/pic_064.jpg 4 +art_painting/guitar/pic_067.jpg 4 +art_painting/guitar/pic_069.jpg 4 +art_painting/guitar/pic_077.jpg 4 +art_painting/guitar/pic_076.jpg 4 +art_painting/guitar/pic_075.jpg 4 +art_painting/guitar/pic_073.jpg 4 +art_painting/guitar/pic_072.jpg 4 +art_painting/guitar/pic_071.jpg 4 +art_painting/guitar/pic_070.jpg 4 +art_painting/guitar/pic_078.jpg 4 +art_painting/guitar/pic_111.jpg 4 +art_painting/guitar/pic_101.jpg 4 +art_painting/guitar/pic_130.jpg 4 +art_painting/guitar/pic_113.jpg 4 +art_painting/guitar/pic_182.jpg 4 +art_painting/guitar/pic_115.jpg 4 +art_painting/guitar/pic_100.jpg 4 +art_painting/guitar/pic_104.jpg 4 +art_painting/guitar/pic_098.jpg 4 +art_painting/guitar/pic_155.jpg 4 +art_painting/guitar/pic_149.jpg 4 +art_painting/guitar/pic_144.jpg 4 +art_painting/guitar/pic_143.jpg 4 +art_painting/guitar/pic_120.jpg 4 +art_painting/guitar/pic_152.jpg 4 +art_painting/guitar/pic_170.jpg 4 +art_painting/guitar/pic_157.jpg 4 +art_painting/guitar/pic_107.jpg 4 +art_painting/guitar/pic_173.jpg 4 +art_painting/guitar/pic_128.jpg 4 +art_painting/guitar/pic_074.jpg 4 +art_painting/guitar/pic_088.jpg 4 +art_painting/guitar/pic_087.jpg 4 +art_painting/guitar/pic_086.jpg 4 +art_painting/guitar/pic_084.jpg 4 +art_painting/guitar/pic_082.jpg 4 +art_painting/guitar/pic_083.jpg 4 +art_painting/guitar/pic_081.jpg 4 +art_painting/guitar/pic_079.jpg 4 +art_painting/guitar/pic_080.jpg 4 +art_painting/guitar/pic_089.jpg 4 +art_painting/guitar/pic_085.jpg 4 +art_painting/guitar/pic_142.jpg 4 +art_painting/guitar/pic_134.jpg 4 +art_painting/guitar/pic_133.jpg 4 +art_painting/guitar/pic_129.jpg 4 +art_painting/guitar/pic_127.jpg 4 +art_painting/guitar/pic_118.jpg 4 +art_painting/guitar/pic_109.jpg 4 +art_painting/guitar/pic_106.jpg 4 +art_painting/guitar/pic_103.jpg 4 +art_painting/guitar/pic_001.jpg 4 +art_painting/guitar/pic_002.jpg 4 +art_painting/guitar/pic_003.jpg 4 +art_painting/guitar/pic_004.jpg 4 +art_painting/guitar/pic_005.jpg 4 +art_painting/guitar/pic_006.jpg 4 +art_painting/guitar/pic_007.jpg 4 +art_painting/guitar/pic_008.jpg 4 +art_painting/guitar/pic_009.jpg 4 +art_painting/guitar/pic_010.jpg 4 +art_painting/guitar/pic_011.jpg 4 +art_painting/guitar/pic_012.jpg 4 +art_painting/guitar/pic_013.jpg 4 +art_painting/guitar/pic_014.jpg 4 +art_painting/guitar/pic_015.jpg 4 +art_painting/guitar/pic_020.jpg 4 +art_painting/guitar/pic_018.jpg 4 +art_painting/guitar/pic_017.jpg 4 +art_painting/guitar/pic_016.jpg 4 +art_painting/guitar/pic_026.jpg 4 +art_painting/guitar/pic_025.jpg 4 +art_painting/guitar/pic_024.jpg 4 +art_painting/guitar/pic_023.jpg 4 +art_painting/guitar/pic_021.jpg 4 +art_painting/guitar/pic_019.jpg 4 +art_painting/guitar/pic_022.jpg 4 +art_painting/guitar/pic_028.jpg 4 +art_painting/guitar/pic_027.jpg 4 +art_painting/guitar/pic_035.jpg 4 +art_painting/guitar/pic_047.jpg 4 +art_painting/guitar/pic_042.jpg 4 +art_painting/guitar/pic_043.jpg 4 +art_painting/guitar/pic_041.jpg 4 +art_painting/guitar/pic_040.jpg 4 +art_painting/guitar/pic_038.jpg 4 +art_painting/guitar/pic_037.jpg 4 +art_painting/guitar/pic_036.jpg 4 +art_painting/guitar/pic_034.jpg 4 +art_painting/guitar/pic_032.jpg 4 +art_painting/guitar/pic_031.jpg 4 +art_painting/guitar/pic_029.jpg 4 +art_painting/guitar/pic_044.jpg 4 +art_painting/guitar/pic_039.jpg 4 +art_painting/guitar/pic_048.jpg 4 +art_painting/guitar/pic_030.jpg 4 +art_painting/guitar/pic_049.jpg 4 +art_painting/guitar/pic_033.jpg 4 +art_painting/guitar/pic_053.jpg 4 +art_painting/guitar/pic_052.jpg 4 +art_painting/guitar/pic_051.jpg 4 +art_painting/guitar/pic_050.jpg 4 +art_painting/guitar/pic_058.jpg 4 +art_painting/guitar/pic_056.jpg 4 +art_painting/guitar/pic_175.jpg 4 +art_painting/guitar/pic_167.jpg 4 +art_painting/guitar/pic_196.jpg 4 +art_painting/guitar/pic_197.jpg 4 +art_painting/guitar/pic_199.jpg 4 +art_painting/guitar/pic_192.jpg 4 +art_painting/guitar/pic_194.jpg 4 +art_painting/guitar/pic_190.jpg 4 +art_painting/guitar/pic_189.jpg 4 +art_painting/guitar/pic_188.jpg 4 +art_painting/guitar/pic_195.jpg 4 +art_painting/guitar/pic_201.jpg 4 +art_painting/guitar/pic_191.jpg 4 +art_painting/guitar/pic_193.jpg 4 +art_painting/guitar/pic_131.jpg 4 +art_painting/guitar/pic_114.jpg 4 +art_painting/guitar/pic_141.jpg 4 +art_painting/guitar/pic_105.jpg 4 +art_painting/guitar/pic_117.jpg 4 +art_painting/guitar/pic_178.jpg 4 +art_painting/guitar/pic_171.jpg 4 +art_painting/guitar/pic_169.jpg 4 +art_painting/guitar/pic_156.jpg 4 +art_painting/guitar/pic_148.jpg 4 +art_painting/guitar/pic_123.jpg 4 +art_painting/guitar/pic_163.jpg 4 +art_painting/guitar/pic_110.jpg 4 +art_painting/guitar/pic_138.jpg 4 +art_painting/guitar/pic_116.jpg 4 +art_painting/guitar/pic_145.jpg 4 +art_painting/guitar/pic_121.jpg 4 +art_painting/guitar/pic_160.jpg 4 +art_painting/guitar/pic_177.jpg 4 +art_painting/guitar/pic_166.jpg 4 +art_painting/guitar/pic_159.jpg 4 +art_painting/guitar/pic_102.jpg 4 +art_painting/guitar/pic_099.jpg 4 +art_painting/guitar/pic_097.jpg 4 +art_painting/guitar/pic_095.jpg 4 +art_painting/guitar/pic_092.jpg 4 +art_painting/guitar/pic_094.jpg 4 +art_painting/guitar/pic_093.jpg 4 +art_painting/guitar/pic_091.jpg 4 +art_painting/guitar/pic_090.jpg 4 +art_painting/guitar/pic_140.jpg 4 +art_painting/guitar/pic_153.jpg 4 +art_painting/guitar/pic_158.jpg 4 +art_painting/guitar/pic_132.jpg 4 +art_painting/guitar/pic_135.jpg 4 +art_painting/guitar/pic_119.jpg 4 +art_painting/guitar/pic_122.jpg 4 +art_painting/guitar/pic_108.jpg 4 +art_painting/guitar/pic_136.jpg 4 +art_painting/guitar/pic_112.jpg 4 +art_painting/horse/pic_034.jpg 5 +art_painting/horse/pic_040.jpg 5 +art_painting/horse/pic_039.jpg 5 +art_painting/horse/pic_042.jpg 5 +art_painting/horse/pic_028.jpg 5 +art_painting/horse/pic_037.jpg 5 +art_painting/horse/pic_041.jpg 5 +art_painting/horse/pic_033.jpg 5 +art_painting/horse/pic_038.jpg 5 +art_painting/horse/pic_025.jpg 5 +art_painting/horse/pic_023.jpg 5 +art_painting/horse/pic_045.jpg 5 +art_painting/horse/pic_030.jpg 5 +art_painting/horse/pic_043.jpg 5 +art_painting/horse/pic_021.jpg 5 +art_painting/horse/pic_026.jpg 5 +art_painting/horse/pic_046.jpg 5 +art_painting/horse/pic_001.jpg 5 +art_painting/horse/pic_002.jpg 5 +art_painting/horse/pic_003.jpg 5 +art_painting/horse/pic_004.jpg 5 +art_painting/horse/pic_005.jpg 5 +art_painting/horse/pic_096.jpg 5 +art_painting/horse/pic_103.jpg 5 +art_painting/horse/pic_110.jpg 5 +art_painting/horse/pic_098.jpg 5 +art_painting/horse/pic_116.jpg 5 +art_painting/horse/pic_120.jpg 5 +art_painting/horse/pic_112.jpg 5 +art_painting/horse/pic_106.jpg 5 +art_painting/horse/pic_123.jpg 5 +art_painting/horse/pic_117.jpg 5 +art_painting/horse/pic_181.jpg 5 +art_painting/horse/pic_141.jpg 5 +art_painting/horse/pic_145.jpg 5 +art_painting/horse/pic_139.jpg 5 +art_painting/horse/pic_138.jpg 5 +art_painting/horse/pic_137.jpg 5 +art_painting/horse/pic_134.jpg 5 +art_painting/horse/pic_135.jpg 5 +art_painting/horse/pic_073.jpg 5 +art_painting/horse/pic_071.jpg 5 +art_painting/horse/pic_072.jpg 5 +art_painting/horse/pic_076.jpg 5 +art_painting/horse/pic_079.jpg 5 +art_painting/horse/pic_081.jpg 5 +art_painting/horse/pic_078.jpg 5 +art_painting/horse/pic_074.jpg 5 +art_painting/horse/pic_077.jpg 5 +art_painting/horse/pic_080.jpg 5 +art_painting/horse/pic_109.jpg 5 +art_painting/horse/pic_104.jpg 5 +art_painting/horse/pic_101.jpg 5 +art_painting/horse/pic_100.jpg 5 +art_painting/horse/pic_097.jpg 5 +art_painting/horse/pic_089.jpg 5 +art_painting/horse/pic_090.jpg 5 +art_painting/horse/pic_091.jpg 5 +art_painting/horse/pic_088.jpg 5 +art_painting/horse/pic_087.jpg 5 +art_painting/horse/pic_083.jpg 5 +art_painting/horse/pic_047.jpg 5 +art_painting/horse/pic_048.jpg 5 +art_painting/horse/pic_049.jpg 5 +art_painting/horse/pic_050.jpg 5 +art_painting/horse/pic_006.jpg 5 +art_painting/horse/pic_007.jpg 5 +art_painting/horse/pic_008.jpg 5 +art_painting/horse/pic_010.jpg 5 +art_painting/horse/pic_011.jpg 5 +art_painting/horse/pic_012.jpg 5 +art_painting/horse/pic_014.jpg 5 +art_painting/horse/pic_015.jpg 5 +art_painting/horse/pic_017.jpg 5 +art_painting/horse/pic_027.jpg 5 +art_painting/horse/pic_019.jpg 5 +art_painting/horse/pic_032.jpg 5 +art_painting/horse/pic_035.jpg 5 +art_painting/horse/pic_024.jpg 5 +art_painting/horse/pic_036.jpg 5 +art_painting/horse/pic_031.jpg 5 +art_painting/horse/pic_160.jpg 5 +art_painting/horse/pic_169.jpg 5 +art_painting/horse/pic_184.jpg 5 +art_painting/horse/pic_179.jpg 5 +art_painting/horse/pic_177.jpg 5 +art_painting/horse/pic_178.jpg 5 +art_painting/horse/pic_176.jpg 5 +art_painting/horse/pic_172.jpg 5 +art_painting/horse/pic_174.jpg 5 +art_painting/horse/pic_173.jpg 5 +art_painting/horse/pic_171.jpg 5 +art_painting/horse/pic_186.jpg 5 +art_painting/horse/pic_199.jpg 5 +art_painting/horse/pic_198.jpg 5 +art_painting/horse/pic_197.jpg 5 +art_painting/horse/pic_191.jpg 5 +art_painting/horse/pic_189.jpg 5 +art_painting/horse/pic_053.jpg 5 +art_painting/horse/pic_051.jpg 5 +art_painting/horse/pic_054.jpg 5 +art_painting/horse/pic_052.jpg 5 +art_painting/horse/pic_057.jpg 5 +art_painting/horse/pic_056.jpg 5 +art_painting/horse/pic_059.jpg 5 +art_painting/horse/pic_060.jpg 5 +art_painting/horse/pic_062.jpg 5 +art_painting/horse/pic_063.jpg 5 +art_painting/horse/pic_061.jpg 5 +art_painting/horse/pic_067.jpg 5 +art_painting/horse/pic_069.jpg 5 +art_painting/horse/pic_066.jpg 5 +art_painting/horse/pic_064.jpg 5 +art_painting/horse/pic_065.jpg 5 +art_painting/horse/pic_070.jpg 5 +art_painting/horse/pic_075.jpg 5 +art_painting/horse/pic_086.jpg 5 +art_painting/horse/pic_082.jpg 5 +art_painting/horse/pic_105.jpg 5 +art_painting/horse/pic_108.jpg 5 +art_painting/horse/pic_107.jpg 5 +art_painting/horse/pic_084.jpg 5 +art_painting/horse/pic_093.jpg 5 +art_painting/horse/pic_099.jpg 5 +art_painting/horse/pic_092.jpg 5 +art_painting/horse/pic_095.jpg 5 +art_painting/horse/pic_121.jpg 5 +art_painting/horse/pic_114.jpg 5 +art_painting/horse/pic_085.jpg 5 +art_painting/horse/pic_113.jpg 5 +art_painting/horse/pic_122.jpg 5 +art_painting/horse/pic_115.jpg 5 +art_painting/horse/pic_102.jpg 5 +art_painting/horse/pic_119.jpg 5 +art_painting/horse/pic_227.jpg 5 +art_painting/horse/pic_226.jpg 5 +art_painting/horse/pic_224.jpg 5 +art_painting/horse/pic_223.jpg 5 +art_painting/horse/pic_222.jpg 5 +art_painting/horse/pic_220.jpg 5 +art_painting/horse/pic_218.jpg 5 +art_painting/horse/pic_217.jpg 5 +art_painting/horse/pic_228.jpg 5 +art_painting/horse/pic_221.jpg 5 +art_painting/horse/pic_219.jpg 5 +art_painting/horse/pic_232.jpg 5 +art_painting/horse/pic_229.jpg 5 +art_painting/horse/pic_193.jpg 5 +art_painting/horse/pic_192.jpg 5 +art_painting/horse/pic_196.jpg 5 +art_painting/horse/pic_200.jpg 5 +art_painting/horse/pic_208.jpg 5 +art_painting/horse/pic_206.jpg 5 +art_painting/horse/pic_203.jpg 5 +art_painting/horse/pic_202.jpg 5 +art_painting/horse/pic_201.jpg 5 +art_painting/horse/pic_209.jpg 5 +art_painting/horse/pic_207.jpg 5 +art_painting/horse/pic_205.jpg 5 +art_painting/horse/pic_210.jpg 5 +art_painting/horse/pic_215.jpg 5 +art_painting/horse/pic_216.jpg 5 +art_painting/horse/pic_212.jpg 5 +art_painting/horse/pic_213.jpg 5 +art_painting/horse/pic_214.jpg 5 +art_painting/horse/pic_225.jpg 5 +art_painting/horse/pic_133.jpg 5 +art_painting/horse/pic_131.jpg 5 +art_painting/horse/pic_125.jpg 5 +art_painting/horse/pic_127.jpg 5 +art_painting/horse/pic_126.jpg 5 +art_painting/horse/pic_156.jpg 5 +art_painting/horse/pic_143.jpg 5 +art_painting/horse/pic_147.jpg 5 +art_painting/horse/pic_144.jpg 5 +art_painting/horse/pic_146.jpg 5 +art_painting/horse/pic_155.jpg 5 +art_painting/horse/pic_142.jpg 5 +art_painting/horse/pic_136.jpg 5 +art_painting/horse/pic_148.jpg 5 +art_painting/horse/pic_162.jpg 5 +art_painting/horse/pic_163.jpg 5 +art_painting/horse/pic_128.jpg 5 +art_painting/horse/pic_154.jpg 5 +art_painting/horse/pic_150.jpg 5 +art_painting/horse/pic_151.jpg 5 +art_painting/horse/pic_152.jpg 5 +art_painting/horse/pic_182.jpg 5 +art_painting/horse/pic_157.jpg 5 +art_painting/horse/pic_130.jpg 5 +art_painting/horse/pic_180.jpg 5 +art_painting/horse/pic_158.jpg 5 +art_painting/horse/pic_204.jpg 5 +art_painting/horse/pic_195.jpg 5 +art_painting/horse/pic_188.jpg 5 +art_painting/horse/pic_159.jpg 5 +art_painting/horse/pic_170.jpg 5 +art_painting/horse/pic_168.jpg 5 +art_painting/horse/pic_165.jpg 5 +art_painting/horse/pic_164.jpg 5 +art_painting/horse/pic_161.jpg 5 +art_painting/house/pic_313.jpg 6 +art_painting/house/pic_169.jpg 6 +art_painting/house/pic_168.jpg 6 +art_painting/house/pic_308.jpg 6 +art_painting/house/pic_167.jpg 6 +art_painting/house/pic_310.jpg 6 +art_painting/house/pic_314.jpg 6 +art_painting/house/pic_170.jpg 6 +art_painting/house/pic_316.jpg 6 +art_painting/house/pic_175.jpg 6 +art_painting/house/pic_173.jpg 6 +art_painting/house/pic_322.jpg 6 +art_painting/house/pic_321.jpg 6 +art_painting/house/pic_320.jpg 6 +art_painting/house/pic_178.jpg 6 +art_painting/house/pic_331.jpg 6 +art_painting/house/pic_001.jpg 6 +art_painting/house/pic_002.jpg 6 +art_painting/house/pic_003.jpg 6 +art_painting/house/pic_004.jpg 6 +art_painting/house/pic_005.jpg 6 +art_painting/house/pic_006.jpg 6 +art_painting/house/pic_007.jpg 6 +art_painting/house/pic_008.jpg 6 +art_painting/house/pic_009.jpg 6 +art_painting/house/pic_010.jpg 6 +art_painting/house/pic_011.jpg 6 +art_painting/house/pic_013.jpg 6 +art_painting/house/pic_015.jpg 6 +art_painting/house/pic_030.jpg 6 +art_painting/house/pic_032.jpg 6 +art_painting/house/pic_019.jpg 6 +art_painting/house/pic_016.jpg 6 +art_painting/house/pic_034.jpg 6 +art_painting/house/pic_022.jpg 6 +art_painting/house/pic_023.jpg 6 +art_painting/house/pic_014.jpg 6 +art_painting/house/pic_025.jpg 6 +art_painting/house/pic_024.jpg 6 +art_painting/house/pic_037.jpg 6 +art_painting/house/pic_018.jpg 6 +art_painting/house/pic_031.jpg 6 +art_painting/house/pic_027.jpg 6 +art_painting/house/pic_029.jpg 6 +art_painting/house/pic_274.jpg 6 +art_painting/house/pic_162.jpg 6 +art_painting/house/pic_160.jpg 6 +art_painting/house/pic_272.jpg 6 +art_painting/house/pic_159.jpg 6 +art_painting/house/pic_161.jpg 6 +art_painting/house/pic_276.jpg 6 +art_painting/house/pic_295.jpg 6 +art_painting/house/pic_165.jpg 6 +art_painting/house/pic_294.jpg 6 +art_painting/house/pic_293.jpg 6 +art_painting/house/pic_163.jpg 6 +art_painting/house/pic_282.jpg 6 +art_painting/house/pic_166.jpg 6 +art_painting/house/pic_164.jpg 6 +art_painting/house/pic_281.jpg 6 +art_painting/house/pic_171.jpg 6 +art_painting/house/pic_311.jpg 6 +art_painting/house/pic_237.jpg 6 +art_painting/house/pic_235.jpg 6 +art_painting/house/pic_234.jpg 6 +art_painting/house/pic_232.jpg 6 +art_painting/house/pic_240.jpg 6 +art_painting/house/pic_251.jpg 6 +art_painting/house/pic_248.jpg 6 +art_painting/house/pic_247.jpg 6 +art_painting/house/pic_246.jpg 6 +art_painting/house/pic_245.jpg 6 +art_painting/house/pic_243.jpg 6 +art_painting/house/pic_242.jpg 6 +art_painting/house/pic_250.jpg 6 +art_painting/house/pic_270.jpg 6 +art_painting/house/pic_269.jpg 6 +art_painting/house/pic_264.jpg 6 +art_painting/house/pic_329.jpg 6 +art_painting/house/pic_297.jpg 6 +art_painting/house/pic_304.jpg 6 +art_painting/house/pic_303.jpg 6 +art_painting/house/pic_302.jpg 6 +art_painting/house/pic_319.jpg 6 +art_painting/house/pic_318.jpg 6 +art_painting/house/pic_317.jpg 6 +art_painting/house/pic_315.jpg 6 +art_painting/house/pic_309.jpg 6 +art_painting/house/pic_306.jpg 6 +art_painting/house/pic_305.jpg 6 +art_painting/house/pic_323.jpg 6 +art_painting/house/pic_324.jpg 6 +art_painting/house/pic_336.jpg 6 +art_painting/house/pic_330.jpg 6 +art_painting/house/pic_327.jpg 6 +art_painting/house/pic_129.jpg 6 +art_painting/house/pic_130.jpg 6 +art_painting/house/pic_131.jpg 6 +art_painting/house/pic_255.jpg 6 +art_painting/house/pic_253.jpg 6 +art_painting/house/pic_133.jpg 6 +art_painting/house/pic_132.jpg 6 +art_painting/house/pic_256.jpg 6 +art_painting/house/pic_134.jpg 6 +art_painting/house/pic_257.jpg 6 +art_painting/house/pic_137.jpg 6 +art_painting/house/pic_258.jpg 6 +art_painting/house/pic_136.jpg 6 +art_painting/house/pic_140.jpg 6 +art_painting/house/pic_142.jpg 6 +art_painting/house/pic_259.jpg 6 +art_painting/house/pic_141.jpg 6 +art_painting/house/pic_146.jpg 6 +art_painting/house/pic_147.jpg 6 +art_painting/house/pic_145.jpg 6 +art_painting/house/pic_254.jpg 6 +art_painting/house/pic_263.jpg 6 +art_painting/house/pic_278.jpg 6 +art_painting/house/pic_277.jpg 6 +art_painting/house/pic_279.jpg 6 +art_painting/house/pic_280.jpg 6 +art_painting/house/pic_283.jpg 6 +art_painting/house/pic_284.jpg 6 +art_painting/house/pic_285.jpg 6 +art_painting/house/pic_287.jpg 6 +art_painting/house/pic_296.jpg 6 +art_painting/house/pic_292.jpg 6 +art_painting/house/pic_289.jpg 6 +art_painting/house/pic_290.jpg 6 +art_painting/house/pic_291.jpg 6 +art_painting/house/pic_301.jpg 6 +art_painting/house/pic_299.jpg 6 +art_painting/house/pic_298.jpg 6 +art_painting/house/pic_189.jpg 6 +art_painting/house/pic_187.jpg 6 +art_painting/house/pic_194.jpg 6 +art_painting/house/pic_206.jpg 6 +art_painting/house/pic_205.jpg 6 +art_painting/house/pic_201.jpg 6 +art_painting/house/pic_200.jpg 6 +art_painting/house/pic_198.jpg 6 +art_painting/house/pic_196.jpg 6 +art_painting/house/pic_197.jpg 6 +art_painting/house/pic_195.jpg 6 +art_painting/house/pic_199.jpg 6 +art_painting/house/pic_203.jpg 6 +art_painting/house/pic_221.jpg 6 +art_painting/house/pic_219.jpg 6 +art_painting/house/pic_217.jpg 6 +art_painting/house/pic_216.jpg 6 +art_painting/house/pic_184.jpg 6 +art_painting/house/pic_181.jpg 6 +art_painting/house/pic_180.jpg 6 +art_painting/house/pic_182.jpg 6 +art_painting/house/pic_335.jpg 6 +art_painting/house/pic_340.jpg 6 +art_painting/house/pic_348.jpg 6 +art_painting/house/pic_185.jpg 6 +art_painting/house/pic_346.jpg 6 +art_painting/house/pic_345.jpg 6 +art_painting/house/pic_344.jpg 6 +art_painting/house/pic_343.jpg 6 +art_painting/house/pic_193.jpg 6 +art_painting/house/pic_192.jpg 6 +art_painting/house/pic_191.jpg 6 +art_painting/house/pic_074.jpg 6 +art_painting/house/pic_076.jpg 6 +art_painting/house/pic_075.jpg 6 +art_painting/house/pic_077.jpg 6 +art_painting/house/pic_087.jpg 6 +art_painting/house/pic_085.jpg 6 +art_painting/house/pic_084.jpg 6 +art_painting/house/pic_083.jpg 6 +art_painting/house/pic_080.jpg 6 +art_painting/house/pic_079.jpg 6 +art_painting/house/pic_078.jpg 6 +art_painting/house/pic_088.jpg 6 +art_painting/house/pic_082.jpg 6 +art_painting/house/pic_086.jpg 6 +art_painting/house/pic_123.jpg 6 +art_painting/house/pic_122.jpg 6 +art_painting/house/pic_119.jpg 6 +art_painting/house/pic_111.jpg 6 +art_painting/house/pic_108.jpg 6 +art_painting/house/pic_104.jpg 6 +art_painting/house/pic_215.jpg 6 +art_painting/house/pic_211.jpg 6 +art_painting/house/pic_209.jpg 6 +art_painting/house/pic_208.jpg 6 +art_painting/house/pic_207.jpg 6 +art_painting/house/pic_218.jpg 6 +art_painting/house/pic_210.jpg 6 +art_painting/house/pic_228.jpg 6 +art_painting/house/pic_227.jpg 6 +art_painting/house/pic_225.jpg 6 +art_painting/house/pic_224.jpg 6 +art_painting/house/pic_223.jpg 6 +art_painting/house/pic_222.jpg 6 +art_painting/house/pic_226.jpg 6 +art_painting/house/pic_230.jpg 6 +art_painting/house/pic_229.jpg 6 +art_painting/house/pic_231.jpg 6 +art_painting/house/pic_241.jpg 6 +art_painting/house/pic_144.jpg 6 +art_painting/house/pic_143.jpg 6 +art_painting/house/pic_149.jpg 6 +art_painting/house/pic_150.jpg 6 +art_painting/house/pic_151.jpg 6 +art_painting/house/pic_148.jpg 6 +art_painting/house/pic_260.jpg 6 +art_painting/house/pic_153.jpg 6 +art_painting/house/pic_152.jpg 6 +art_painting/house/pic_261.jpg 6 +art_painting/house/pic_262.jpg 6 +art_painting/house/pic_268.jpg 6 +art_painting/house/pic_156.jpg 6 +art_painting/house/pic_158.jpg 6 +art_painting/house/pic_157.jpg 6 +art_painting/house/pic_266.jpg 6 +art_painting/house/pic_267.jpg 6 +art_painting/house/pic_273.jpg 6 +art_painting/house/pic_097.jpg 6 +art_painting/house/pic_118.jpg 6 +art_painting/house/pic_114.jpg 6 +art_painting/house/pic_094.jpg 6 +art_painting/house/pic_101.jpg 6 +art_painting/house/pic_125.jpg 6 +art_painting/house/pic_113.jpg 6 +art_painting/house/pic_109.jpg 6 +art_painting/house/pic_098.jpg 6 +art_painting/house/pic_116.jpg 6 +art_painting/house/pic_127.jpg 6 +art_painting/house/pic_120.jpg 6 +art_painting/house/pic_138.jpg 6 +art_painting/house/pic_176.jpg 6 +art_painting/house/pic_177.jpg 6 +art_painting/house/pic_212.jpg 6 +art_painting/house/pic_213.jpg 6 +art_painting/house/pic_238.jpg 6 +art_painting/house/pic_128.jpg 6 +art_painting/house/pic_053.jpg 6 +art_painting/house/pic_055.jpg 6 +art_painting/house/pic_054.jpg 6 +art_painting/house/pic_057.jpg 6 +art_painting/house/pic_056.jpg 6 +art_painting/house/pic_058.jpg 6 +art_painting/house/pic_059.jpg 6 +art_painting/house/pic_061.jpg 6 +art_painting/house/pic_060.jpg 6 +art_painting/house/pic_062.jpg 6 +art_painting/house/pic_063.jpg 6 +art_painting/house/pic_067.jpg 6 +art_painting/house/pic_069.jpg 6 +art_painting/house/pic_068.jpg 6 +art_painting/house/pic_066.jpg 6 +art_painting/house/pic_071.jpg 6 +art_painting/house/pic_070.jpg 6 +art_painting/house/pic_072.jpg 6 +art_painting/house/pic_106.jpg 6 +art_painting/house/pic_107.jpg 6 +art_painting/house/pic_099.jpg 6 +art_painting/house/pic_100.jpg 6 +art_painting/house/pic_035.jpg 6 +art_painting/house/pic_095.jpg 6 +art_painting/house/pic_093.jpg 6 +art_painting/house/pic_090.jpg 6 +art_painting/house/pic_092.jpg 6 +art_painting/house/pic_091.jpg 6 +art_painting/house/pic_103.jpg 6 +art_painting/house/pic_124.jpg 6 +art_painting/house/pic_110.jpg 6 +art_painting/house/pic_117.jpg 6 +art_painting/house/pic_105.jpg 6 +art_painting/house/pic_121.jpg 6 +art_painting/house/pic_115.jpg 6 +art_painting/house/pic_028.jpg 6 +art_painting/house/pic_017.jpg 6 +art_painting/house/pic_038.jpg 6 +art_painting/house/pic_048.jpg 6 +art_painting/house/pic_047.jpg 6 +art_painting/house/pic_036.jpg 6 +art_painting/house/pic_043.jpg 6 +art_painting/house/pic_041.jpg 6 +art_painting/house/pic_040.jpg 6 +art_painting/house/pic_039.jpg 6 +art_painting/house/pic_021.jpg 6 +art_painting/house/pic_020.jpg 6 +art_painting/house/pic_026.jpg 6 +art_painting/house/pic_046.jpg 6 +art_painting/house/pic_044.jpg 6 +art_painting/house/pic_045.jpg 6 +art_painting/house/pic_042.jpg 6 +art_painting/house/pic_049.jpg 6 +art_painting/house/pic_050.jpg 6 +art_painting/house/pic_051.jpg 6 +art_painting/person/pic_280.jpg 7 +art_painting/person/pic_278.jpg 7 +art_painting/person/pic_277.jpg 7 +art_painting/person/pic_276.jpg 7 +art_painting/person/pic_275.jpg 7 +art_painting/person/pic_273.jpg 7 +art_painting/person/pic_284.jpg 7 +art_painting/person/pic_283.jpg 7 +art_painting/person/pic_281.jpg 7 +art_painting/person/pic_282.jpg 7 +art_painting/person/pic_285.jpg 7 +art_painting/person/pic_269.jpg 7 +art_painting/person/pic_297.jpg 7 +art_painting/person/pic_298.jpg 7 +art_painting/person/pic_296.jpg 7 +art_painting/person/pic_295.jpg 7 +art_painting/person/pic_134.jpg 7 +art_painting/person/pic_133.jpg 7 +art_painting/person/pic_135.jpg 7 +art_painting/person/pic_310.jpg 7 +art_painting/person/pic_141.jpg 7 +art_painting/person/pic_001.jpg 7 +art_painting/person/pic_002.jpg 7 +art_painting/person/pic_003.jpg 7 +art_painting/person/pic_004.jpg 7 +art_painting/person/pic_005.jpg 7 +art_painting/person/pic_048.jpg 7 +art_painting/person/pic_050.jpg 7 +art_painting/person/pic_052.jpg 7 +art_painting/person/pic_055.jpg 7 +art_painting/person/pic_056.jpg 7 +art_painting/person/pic_065.jpg 7 +art_painting/person/pic_331.jpg 7 +art_painting/person/pic_330.jpg 7 +art_painting/person/pic_176.jpg 7 +art_painting/person/pic_416.jpg 7 +art_painting/person/pic_420.jpg 7 +art_painting/person/pic_426.jpg 7 +art_painting/person/pic_424.jpg 7 +art_painting/person/pic_423.jpg 7 +art_painting/person/pic_421.jpg 7 +art_painting/person/pic_183.jpg 7 +art_painting/person/pic_428.jpg 7 +art_painting/person/pic_430.jpg 7 +art_painting/person/pic_429.jpg 7 +art_painting/person/pic_436.jpg 7 +art_painting/person/pic_437.jpg 7 +art_painting/person/pic_438.jpg 7 +art_painting/person/pic_184.jpg 7 +art_painting/person/pic_186.jpg 7 +art_painting/person/pic_388.jpg 7 +art_painting/person/pic_410.jpg 7 +art_painting/person/pic_400.jpg 7 +art_painting/person/pic_391.jpg 7 +art_painting/person/pic_406.jpg 7 +art_painting/person/pic_407.jpg 7 +art_painting/person/pic_417.jpg 7 +art_painting/person/pic_435.jpg 7 +art_painting/person/pic_433.jpg 7 +art_painting/person/pic_431.jpg 7 +art_painting/person/pic_467.jpg 7 +art_painting/person/pic_247.jpg 7 +art_painting/person/pic_249.jpg 7 +art_painting/person/pic_252.jpg 7 +art_painting/person/pic_255.jpg 7 +art_painting/person/pic_531.jpg 7 +art_painting/person/pic_530.jpg 7 +art_painting/person/pic_264.jpg 7 +art_painting/person/pic_262.jpg 7 +art_painting/person/pic_549.jpg 7 +art_painting/person/pic_260.jpg 7 +art_painting/person/pic_548.jpg 7 +art_painting/person/pic_501.jpg 7 +art_painting/person/pic_495.jpg 7 +art_painting/person/pic_494.jpg 7 +art_painting/person/pic_506.jpg 7 +art_painting/person/pic_532.jpg 7 +art_painting/person/pic_527.jpg 7 +art_painting/person/pic_525.jpg 7 +art_painting/person/pic_519.jpg 7 +art_painting/person/pic_523.jpg 7 +art_painting/person/pic_521.jpg 7 +art_painting/person/pic_520.jpg 7 +art_painting/person/pic_512.jpg 7 +art_painting/person/pic_528.jpg 7 +art_painting/person/pic_526.jpg 7 +art_painting/person/pic_518.jpg 7 +art_painting/person/pic_534.jpg 7 +art_painting/person/pic_538.jpg 7 +art_painting/person/pic_026.jpg 7 +art_painting/person/pic_047.jpg 7 +art_painting/person/pic_030.jpg 7 +art_painting/person/pic_022.jpg 7 +art_painting/person/pic_032.jpg 7 +art_painting/person/pic_024.jpg 7 +art_painting/person/pic_044.jpg 7 +art_painting/person/pic_038.jpg 7 +art_painting/person/pic_027.jpg 7 +art_painting/person/pic_019.jpg 7 +art_painting/person/pic_034.jpg 7 +art_painting/person/pic_045.jpg 7 +art_painting/person/pic_023.jpg 7 +art_painting/person/pic_029.jpg 7 +art_painting/person/pic_025.jpg 7 +art_painting/person/pic_041.jpg 7 +art_painting/person/pic_039.jpg 7 +art_painting/person/pic_031.jpg 7 +art_painting/person/pic_046.jpg 7 +art_painting/person/pic_020.jpg 7 +art_painting/person/pic_040.jpg 7 +art_painting/person/pic_226.jpg 7 +art_painting/person/pic_229.jpg 7 +art_painting/person/pic_228.jpg 7 +art_painting/person/pic_484.jpg 7 +art_painting/person/pic_234.jpg 7 +art_painting/person/pic_231.jpg 7 +art_painting/person/pic_232.jpg 7 +art_painting/person/pic_235.jpg 7 +art_painting/person/pic_505.jpg 7 +art_painting/person/pic_243.jpg 7 +art_painting/person/pic_237.jpg 7 +art_painting/person/pic_456.jpg 7 +art_painting/person/pic_200.jpg 7 +art_painting/person/pic_459.jpg 7 +art_painting/person/pic_460.jpg 7 +art_painting/person/pic_203.jpg 7 +art_painting/person/pic_206.jpg 7 +art_painting/person/pic_204.jpg 7 +art_painting/person/pic_202.jpg 7 +art_painting/person/pic_201.jpg 7 +art_painting/person/pic_462.jpg 7 +art_painting/person/pic_205.jpg 7 +art_painting/person/pic_213.jpg 7 +art_painting/person/pic_470.jpg 7 +art_painting/person/pic_469.jpg 7 +art_painting/person/pic_464.jpg 7 +art_painting/person/pic_209.jpg 7 +art_painting/person/pic_208.jpg 7 +art_painting/person/pic_210.jpg 7 +art_painting/person/pic_497.jpg 7 +art_painting/person/pic_236.jpg 7 +art_painting/person/pic_496.jpg 7 +art_painting/person/pic_503.jpg 7 +art_painting/person/pic_238.jpg 7 +art_painting/person/pic_508.jpg 7 +art_painting/person/pic_507.jpg 7 +art_painting/person/pic_504.jpg 7 +art_painting/person/pic_245.jpg 7 +art_painting/person/pic_254.jpg 7 +art_painting/person/pic_253.jpg 7 +art_painting/person/pic_522.jpg 7 +art_painting/person/pic_248.jpg 7 +art_painting/person/pic_514.jpg 7 +art_painting/person/pic_513.jpg 7 +art_painting/person/pic_246.jpg 7 +art_painting/person/pic_250.jpg 7 +art_painting/person/pic_132.jpg 7 +art_painting/person/pic_116.jpg 7 +art_painting/person/pic_104.jpg 7 +art_painting/person/pic_112.jpg 7 +art_painting/person/pic_100.jpg 7 +art_painting/person/pic_117.jpg 7 +art_painting/person/pic_122.jpg 7 +art_painting/person/pic_121.jpg 7 +art_painting/person/pic_129.jpg 7 +art_painting/person/pic_136.jpg 7 +art_painting/person/pic_193.jpg 7 +art_painting/person/pic_194.jpg 7 +art_painting/person/pic_192.jpg 7 +art_painting/person/pic_195.jpg 7 +art_painting/person/pic_241.jpg 7 +art_painting/person/pic_242.jpg 7 +art_painting/person/pic_240.jpg 7 +art_painting/person/pic_152.jpg 7 +art_painting/person/pic_170.jpg 7 +art_painting/person/pic_171.jpg 7 +art_painting/person/pic_168.jpg 7 +art_painting/person/pic_167.jpg 7 +art_painting/person/pic_320.jpg 7 +art_painting/person/pic_319.jpg 7 +art_painting/person/pic_318.jpg 7 +art_painting/person/pic_164.jpg 7 +art_painting/person/pic_163.jpg 7 +art_painting/person/pic_162.jpg 7 +art_painting/person/pic_161.jpg 7 +art_painting/person/pic_316.jpg 7 +art_painting/person/pic_160.jpg 7 +art_painting/person/pic_321.jpg 7 +art_painting/person/pic_165.jpg 7 +art_painting/person/pic_317.jpg 7 +art_painting/person/pic_166.jpg 7 +art_painting/person/pic_169.jpg 7 +art_painting/person/pic_535.jpg 7 +art_painting/person/pic_543.jpg 7 +art_painting/person/pic_540.jpg 7 +art_painting/person/pic_539.jpg 7 +art_painting/person/pic_542.jpg 7 +art_painting/person/pic_545.jpg 7 +art_painting/person/pic_559.jpg 7 +art_painting/person/pic_555.jpg 7 +art_painting/person/pic_553.jpg 7 +art_painting/person/pic_551.jpg 7 +art_painting/person/pic_552.jpg 7 +art_painting/person/pic_550.jpg 7 +art_painting/person/pic_546.jpg 7 +art_painting/person/pic_556.jpg 7 +art_painting/person/pic_558.jpg 7 +art_painting/person/pic_572.jpg 7 +art_painting/person/pic_571.jpg 7 +art_painting/person/pic_570.jpg 7 +art_painting/person/pic_564.jpg 7 +art_painting/person/pic_563.jpg 7 +art_painting/person/pic_560.jpg 7 +art_painting/person/pic_561.jpg 7 +art_painting/person/pic_577.jpg 7 +art_painting/person/pic_259.jpg 7 +art_painting/person/pic_547.jpg 7 +art_painting/person/pic_257.jpg 7 +art_painting/person/pic_256.jpg 7 +art_painting/person/pic_537.jpg 7 +art_painting/person/pic_536.jpg 7 +art_painting/person/pic_263.jpg 7 +art_painting/person/pic_051.jpg 7 +art_painting/person/pic_268.jpg 7 +art_painting/person/pic_574.jpg 7 +art_painting/person/pic_573.jpg 7 +art_painting/person/pic_267.jpg 7 +art_painting/person/pic_266.jpg 7 +art_painting/person/pic_265.jpg 7 +art_painting/person/pic_272.jpg 7 +art_painting/person/pic_568.jpg 7 +art_painting/person/pic_569.jpg 7 +art_painting/person/pic_271.jpg 7 +art_painting/person/pic_113.jpg 7 +art_painting/person/pic_111.jpg 7 +art_painting/person/pic_109.jpg 7 +art_painting/person/pic_107.jpg 7 +art_painting/person/pic_106.jpg 7 +art_painting/person/pic_105.jpg 7 +art_painting/person/pic_101.jpg 7 +art_painting/person/pic_099.jpg 7 +art_painting/person/pic_131.jpg 7 +art_painting/person/pic_120.jpg 7 +art_painting/person/pic_110.jpg 7 +art_painting/person/pic_123.jpg 7 +art_painting/person/pic_108.jpg 7 +art_painting/person/pic_098.jpg 7 +art_painting/person/pic_364.jpg 7 +art_painting/person/pic_363.jpg 7 +art_painting/person/pic_356.jpg 7 +art_painting/person/pic_357.jpg 7 +art_painting/person/pic_366.jpg 7 +art_painting/person/pic_372.jpg 7 +art_painting/person/pic_377.jpg 7 +art_painting/person/pic_378.jpg 7 +art_painting/person/pic_376.jpg 7 +art_painting/person/pic_371.jpg 7 +art_painting/person/pic_375.jpg 7 +art_painting/person/pic_389.jpg 7 +art_painting/person/pic_387.jpg 7 +art_painting/person/pic_386.jpg 7 +art_painting/person/pic_385.jpg 7 +art_painting/person/pic_379.jpg 7 +art_painting/person/pic_214.jpg 7 +art_painting/person/pic_211.jpg 7 +art_painting/person/pic_471.jpg 7 +art_painting/person/pic_475.jpg 7 +art_painting/person/pic_220.jpg 7 +art_painting/person/pic_218.jpg 7 +art_painting/person/pic_216.jpg 7 +art_painting/person/pic_215.jpg 7 +art_painting/person/pic_221.jpg 7 +art_painting/person/pic_217.jpg 7 +art_painting/person/pic_219.jpg 7 +art_painting/person/pic_227.jpg 7 +art_painting/person/pic_480.jpg 7 +art_painting/person/pic_479.jpg 7 +art_painting/person/pic_476.jpg 7 +art_painting/person/pic_224.jpg 7 +art_painting/person/pic_223.jpg 7 +art_painting/person/pic_222.jpg 7 +art_painting/person/pic_322.jpg 7 +art_painting/person/pic_306.jpg 7 +art_painting/person/pic_333.jpg 7 +art_painting/person/pic_346.jpg 7 +art_painting/person/pic_354.jpg 7 +art_painting/person/pic_353.jpg 7 +art_painting/person/pic_352.jpg 7 +art_painting/person/pic_351.jpg 7 +art_painting/person/pic_349.jpg 7 +art_painting/person/pic_347.jpg 7 +art_painting/person/pic_345.jpg 7 +art_painting/person/pic_338.jpg 7 +art_painting/person/pic_337.jpg 7 +art_painting/person/pic_350.jpg 7 +art_painting/person/pic_339.jpg 7 +art_painting/person/pic_368.jpg 7 +art_painting/person/pic_308.jpg 7 +art_painting/person/pic_151.jpg 7 +art_painting/person/pic_150.jpg 7 +art_painting/person/pic_149.jpg 7 +art_painting/person/pic_313.jpg 7 +art_painting/person/pic_148.jpg 7 +art_painting/person/pic_146.jpg 7 +art_painting/person/pic_311.jpg 7 +art_painting/person/pic_143.jpg 7 +art_painting/person/pic_144.jpg 7 +art_painting/person/pic_147.jpg 7 +art_painting/person/pic_145.jpg 7 +art_painting/person/pic_312.jpg 7 +art_painting/person/pic_314.jpg 7 +art_painting/person/pic_158.jpg 7 +art_painting/person/pic_157.jpg 7 +art_painting/person/pic_156.jpg 7 +art_painting/person/pic_155.jpg 7 +art_painting/person/pic_290.jpg 7 +art_painting/person/pic_288.jpg 7 +art_painting/person/pic_287.jpg 7 +art_painting/person/pic_294.jpg 7 +art_painting/person/pic_293.jpg 7 +art_painting/person/pic_292.jpg 7 +art_painting/person/pic_291.jpg 7 +art_painting/person/pic_301.jpg 7 +art_painting/person/pic_300.jpg 7 +art_painting/person/pic_305.jpg 7 +art_painting/person/pic_303.jpg 7 +art_painting/person/pic_304.jpg 7 +art_painting/person/pic_336.jpg 7 +art_painting/person/pic_325.jpg 7 +art_painting/person/pic_324.jpg 7 +art_painting/person/pic_006.jpg 7 +art_painting/person/pic_007.jpg 7 +art_painting/person/pic_008.jpg 7 +art_painting/person/pic_009.jpg 7 +art_painting/person/pic_010.jpg 7 +art_painting/person/pic_011.jpg 7 +art_painting/person/pic_012.jpg 7 +art_painting/person/pic_013.jpg 7 +art_painting/person/pic_014.jpg 7 +art_painting/person/pic_015.jpg 7 +art_painting/person/pic_016.jpg 7 +art_painting/person/pic_042.jpg 7 +art_painting/person/pic_033.jpg 7 +art_painting/person/pic_018.jpg 7 +art_painting/person/pic_036.jpg 7 +art_painting/person/pic_017.jpg 7 +art_painting/person/pic_037.jpg 7 +art_painting/person/pic_028.jpg 7 +art_painting/person/pic_043.jpg 7 +art_painting/person/pic_035.jpg 7 +art_painting/person/pic_327.jpg 7 +art_painting/person/pic_175.jpg 7 +art_painting/person/pic_328.jpg 7 +art_painting/person/pic_326.jpg 7 +art_painting/person/pic_174.jpg 7 +art_painting/person/pic_172.jpg 7 +art_painting/person/pic_329.jpg 7 +art_painting/person/pic_173.jpg 7 +art_painting/person/pic_178.jpg 7 +art_painting/person/pic_334.jpg 7 +art_painting/person/pic_335.jpg 7 +art_painting/person/pic_342.jpg 7 +art_painting/person/pic_181.jpg 7 +art_painting/person/pic_343.jpg 7 +art_painting/person/pic_180.jpg 7 +art_painting/person/pic_340.jpg 7 +art_painting/person/pic_359.jpg 7 +art_painting/person/pic_064.jpg 7 +art_painting/person/pic_062.jpg 7 +art_painting/person/pic_059.jpg 7 +art_painting/person/pic_060.jpg 7 +art_painting/person/pic_066.jpg 7 +art_painting/person/pic_063.jpg 7 +art_painting/person/pic_071.jpg 7 +art_painting/person/pic_070.jpg 7 +art_painting/person/pic_069.jpg 7 +art_painting/person/pic_072.jpg 7 +art_painting/person/pic_076.jpg 7 +art_painting/person/pic_074.jpg 7 +art_painting/person/pic_077.jpg 7 +art_painting/person/pic_078.jpg 7 +art_painting/person/pic_079.jpg 7 +art_painting/person/pic_080.jpg 7 +art_painting/person/pic_081.jpg 7 +art_painting/person/pic_082.jpg 7 +art_painting/person/pic_083.jpg 7 +art_painting/person/pic_094.jpg 7 +art_painting/person/pic_093.jpg 7 +art_painting/person/pic_089.jpg 7 +art_painting/person/pic_090.jpg 7 +art_painting/person/pic_086.jpg 7 +art_painting/person/pic_097.jpg 7 +art_painting/person/pic_124.jpg 7 +art_painting/person/pic_128.jpg 7 +art_painting/person/pic_127.jpg 7 +art_painting/person/pic_126.jpg 7 +art_painting/person/pic_115.jpg 7 +art_painting/person/pic_114.jpg 7 +art_painting/person/pic_463.jpg 7 +art_painting/person/pic_458.jpg 7 +art_painting/person/pic_444.jpg 7 +art_painting/person/pic_445.jpg 7 +art_painting/person/pic_466.jpg 7 +art_painting/person/pic_465.jpg 7 +art_painting/person/pic_493.jpg 7 +art_painting/person/pic_490.jpg 7 +art_painting/person/pic_487.jpg 7 +art_painting/person/pic_481.jpg 7 +art_painting/person/pic_474.jpg 7 +art_painting/person/pic_468.jpg 7 +art_painting/person/pic_492.jpg 7 +art_painting/person/pic_473.jpg 7 +art_painting/person/pic_511.jpg 7 +art_painting/person/pic_510.jpg 7 +art_painting/person/pic_502.jpg 7 +art_painting/person/pic_187.jpg 7 +art_painting/person/pic_441.jpg 7 +art_painting/person/pic_440.jpg 7 +art_painting/person/pic_188.jpg 7 +art_painting/person/pic_450.jpg 7 +art_painting/person/pic_449.jpg 7 +art_painting/person/pic_448.jpg 7 +art_painting/person/pic_447.jpg 7 +art_painting/person/pic_190.jpg 7 +art_painting/person/pic_454.jpg 7 +art_painting/person/pic_455.jpg 7 +art_painting/person/pic_199.jpg 7 +art_painting/person/pic_197.jpg 7 +art_painting/person/pic_198.jpg 7 +art_painting/person/pic_196.jpg 7 +art_painting/person/pic_191.jpg 7 +art_painting/person/pic_358.jpg 7 +art_painting/person/pic_361.jpg 7 +art_painting/person/pic_362.jpg 7 +art_painting/person/pic_382.jpg 7 +art_painting/person/pic_380.jpg 7 +art_painting/person/pic_381.jpg 7 +art_painting/person/pic_383.jpg 7 +art_painting/person/pic_398.jpg 7 +art_painting/person/pic_395.jpg 7 +art_painting/person/pic_394.jpg 7 +art_painting/person/pic_396.jpg 7 +art_painting/person/pic_397.jpg 7 +art_painting/person/pic_402.jpg 7 +art_painting/person/pic_404.jpg 7 +art_painting/person/pic_405.jpg 7 +art_painting/person/pic_412.jpg 7 +art_painting/person/pic_414.jpg 7 +art_painting/person/pic_413.jpg 7 diff --git a/domainlab/zdata/pacs_split/art_painting_train_kfold.txt b/domainlab/zdata/pacs_split/art_painting_train_kfold.txt new file mode 100644 index 000000000..8b5405715 --- /dev/null +++ b/domainlab/zdata/pacs_split/art_painting_train_kfold.txt @@ -0,0 +1,1840 @@ +art_painting/dog/pic_333.jpg 1 +art_painting/dog/pic_376.jpg 1 +art_painting/dog/pic_259.jpg 1 +art_painting/dog/pic_261.jpg 1 +art_painting/dog/pic_256.jpg 1 +art_painting/dog/pic_253.jpg 1 +art_painting/dog/pic_265.jpg 1 +art_painting/dog/pic_258.jpg 1 +art_painting/dog/pic_279.jpg 1 +art_painting/dog/pic_324.jpg 1 +art_painting/dog/pic_325.jpg 1 +art_painting/dog/pic_332.jpg 1 +art_painting/dog/pic_251.jpg 1 +art_painting/dog/pic_275.jpg 1 +art_painting/dog/pic_276.jpg 1 +art_painting/dog/pic_269.jpg 1 +art_painting/dog/pic_267.jpg 1 +art_painting/dog/pic_334.jpg 1 +art_painting/dog/pic_278.jpg 1 +art_painting/dog/pic_266.jpg 1 +art_painting/dog/pic_340.jpg 1 +art_painting/dog/pic_198.jpg 1 +art_painting/dog/pic_166.jpg 1 +art_painting/dog/pic_196.jpg 1 +art_painting/dog/pic_268.jpg 1 +art_painting/dog/pic_192.jpg 1 +art_painting/dog/pic_272.jpg 1 +art_painting/dog/pic_274.jpg 1 +art_painting/dog/pic_209.jpg 1 +art_painting/dog/pic_201.jpg 1 +art_painting/dog/pic_205.jpg 1 +art_painting/dog/pic_208.jpg 1 +art_painting/dog/pic_210.jpg 1 +art_painting/dog/pic_226.jpg 1 +art_painting/dog/pic_221.jpg 1 +art_painting/dog/pic_281.jpg 1 +art_painting/dog/pic_193.jpg 1 +art_painting/dog/pic_199.jpg 1 +art_painting/dog/pic_188.jpg 1 +art_painting/dog/pic_234.jpg 1 +art_painting/dog/pic_009.jpg 1 +art_painting/dog/pic_010.jpg 1 +art_painting/dog/pic_011.jpg 1 +art_painting/dog/pic_012.jpg 1 +art_painting/dog/pic_013.jpg 1 +art_painting/dog/pic_014.jpg 1 +art_painting/dog/pic_015.jpg 1 +art_painting/dog/pic_016.jpg 1 +art_painting/dog/pic_017.jpg 1 +art_painting/dog/pic_018.jpg 1 +art_painting/dog/pic_019.jpg 1 +art_painting/dog/pic_023.jpg 1 +art_painting/dog/pic_020.jpg 1 +art_painting/dog/pic_022.jpg 1 +art_painting/dog/pic_031.jpg 1 +art_painting/dog/pic_026.jpg 1 +art_painting/dog/pic_029.jpg 1 +art_painting/dog/pic_028.jpg 1 +art_painting/dog/pic_025.jpg 1 +art_painting/dog/pic_032.jpg 1 +art_painting/dog/pic_113.jpg 1 +art_painting/dog/pic_116.jpg 1 +art_painting/dog/pic_121.jpg 1 +art_painting/dog/pic_118.jpg 1 +art_painting/dog/pic_132.jpg 1 +art_painting/dog/pic_105.jpg 1 +art_painting/dog/pic_114.jpg 1 +art_painting/dog/pic_237.jpg 1 +art_painting/dog/pic_239.jpg 1 +art_painting/dog/pic_177.jpg 1 +art_painting/dog/pic_172.jpg 1 +art_painting/dog/pic_170.jpg 1 +art_painting/dog/pic_169.jpg 1 +art_painting/dog/pic_240.jpg 1 +art_painting/dog/pic_244.jpg 1 +art_painting/dog/pic_243.jpg 1 +art_painting/dog/pic_127.jpg 1 +art_painting/dog/pic_146.jpg 1 +art_painting/dog/pic_130.jpg 1 +art_painting/dog/pic_143.jpg 1 +art_painting/dog/pic_148.jpg 1 +art_painting/dog/pic_140.jpg 1 +art_painting/dog/pic_246.jpg 1 +art_painting/dog/pic_147.jpg 1 +art_painting/dog/pic_139.jpg 1 +art_painting/dog/pic_144.jpg 1 +art_painting/dog/pic_176.jpg 1 +art_painting/dog/pic_153.jpg 1 +art_painting/dog/pic_187.jpg 1 +art_painting/dog/pic_165.jpg 1 +art_painting/dog/pic_163.jpg 1 +art_painting/dog/pic_167.jpg 1 +art_painting/dog/pic_164.jpg 1 +art_painting/dog/pic_181.jpg 1 +art_painting/dog/pic_183.jpg 1 +art_painting/dog/pic_401.jpg 1 +art_painting/dog/pic_395.jpg 1 +art_painting/dog/pic_412.jpg 1 +art_painting/dog/pic_409.jpg 1 +art_painting/dog/pic_414.jpg 1 +art_painting/dog/pic_407.jpg 1 +art_painting/dog/pic_404.jpg 1 +art_painting/dog/pic_415.jpg 1 +art_painting/dog/pic_410.jpg 1 +art_painting/dog/pic_413.jpg 1 +art_painting/dog/pic_408.jpg 1 +art_painting/dog/pic_382.jpg 1 +art_painting/dog/pic_342.jpg 1 +art_painting/dog/pic_343.jpg 1 +art_painting/dog/pic_271.jpg 1 +art_painting/dog/pic_280.jpg 1 +art_painting/dog/pic_303.jpg 1 +art_painting/dog/pic_349.jpg 1 +art_painting/dog/pic_290.jpg 1 +art_painting/dog/pic_289.jpg 1 +art_painting/dog/pic_287.jpg 1 +art_painting/dog/pic_284.jpg 1 +art_painting/dog/pic_283.jpg 1 +art_painting/dog/pic_286.jpg 1 +art_painting/dog/pic_307.jpg 1 +art_painting/dog/pic_293.jpg 1 +art_painting/dog/pic_299.jpg 1 +art_painting/dog/pic_288.jpg 1 +art_painting/dog/pic_354.jpg 1 +art_painting/dog/pic_358.jpg 1 +art_painting/dog/pic_295.jpg 1 +art_painting/dog/pic_292.jpg 1 +art_painting/dog/pic_400.jpg 1 +art_painting/dog/pic_351.jpg 1 +art_painting/dog/pic_350.jpg 1 +art_painting/dog/pic_348.jpg 1 +art_painting/dog/pic_346.jpg 1 +art_painting/dog/pic_405.jpg 1 +art_painting/dog/pic_411.jpg 1 +art_painting/dog/pic_406.jpg 1 +art_painting/dog/pic_357.jpg 1 +art_painting/dog/pic_359.jpg 1 +art_painting/dog/pic_369.jpg 1 +art_painting/dog/pic_355.jpg 1 +art_painting/dog/pic_360.jpg 1 +art_painting/dog/pic_377.jpg 1 +art_painting/dog/pic_361.jpg 1 +art_painting/dog/pic_367.jpg 1 +art_painting/dog/pic_362.jpg 1 +art_painting/dog/pic_372.jpg 1 +art_painting/dog/pic_370.jpg 1 +art_painting/dog/pic_366.jpg 1 +art_painting/dog/pic_375.jpg 1 +art_painting/dog/pic_374.jpg 1 +art_painting/dog/pic_368.jpg 1 +art_painting/dog/pic_392.jpg 1 +art_painting/dog/pic_380.jpg 1 +art_painting/dog/pic_381.jpg 1 +art_painting/dog/pic_386.jpg 1 +art_painting/dog/pic_385.jpg 1 +art_painting/dog/pic_384.jpg 1 +art_painting/dog/pic_378.jpg 1 +art_painting/dog/pic_383.jpg 1 +art_painting/dog/pic_393.jpg 1 +art_painting/dog/pic_388.jpg 1 +art_painting/dog/pic_394.jpg 1 +art_painting/dog/pic_391.jpg 1 +art_painting/dog/pic_390.jpg 1 +art_painting/dog/pic_399.jpg 1 +art_painting/dog/pic_396.jpg 1 +art_painting/dog/pic_110.jpg 1 +art_painting/dog/pic_120.jpg 1 +art_painting/dog/pic_123.jpg 1 +art_painting/dog/pic_112.jpg 1 +art_painting/dog/pic_126.jpg 1 +art_painting/dog/pic_065.jpg 1 +art_painting/dog/pic_064.jpg 1 +art_painting/dog/pic_066.jpg 1 +art_painting/dog/pic_062.jpg 1 +art_painting/dog/pic_070.jpg 1 +art_painting/dog/pic_131.jpg 1 +art_painting/dog/pic_133.jpg 1 +art_painting/dog/pic_136.jpg 1 +art_painting/dog/pic_145.jpg 1 +art_painting/dog/pic_149.jpg 1 +art_painting/dog/pic_152.jpg 1 +art_painting/dog/pic_151.jpg 1 +art_painting/dog/pic_179.jpg 1 +art_painting/dog/pic_178.jpg 1 +art_painting/dog/pic_182.jpg 1 +art_painting/dog/pic_109.jpg 1 +art_painting/dog/pic_107.jpg 1 +art_painting/dog/pic_185.jpg 1 +art_painting/dog/pic_106.jpg 1 +art_painting/dog/pic_083.jpg 1 +art_painting/dog/pic_088.jpg 1 +art_painting/dog/pic_087.jpg 1 +art_painting/dog/pic_089.jpg 1 +art_painting/dog/pic_103.jpg 1 +art_painting/dog/pic_124.jpg 1 +art_painting/dog/pic_150.jpg 1 +art_painting/dog/pic_137.jpg 1 +art_painting/dog/pic_092.jpg 1 +art_painting/dog/pic_085.jpg 1 +art_painting/dog/pic_001.jpg 1 +art_painting/dog/pic_002.jpg 1 +art_painting/dog/pic_003.jpg 1 +art_painting/dog/pic_004.jpg 1 +art_painting/dog/pic_005.jpg 1 +art_painting/dog/pic_006.jpg 1 +art_painting/dog/pic_007.jpg 1 +art_painting/dog/pic_008.jpg 1 +art_painting/dog/pic_055.jpg 1 +art_painting/dog/pic_048.jpg 1 +art_painting/dog/pic_047.jpg 1 +art_painting/dog/pic_052.jpg 1 +art_painting/dog/pic_050.jpg 1 +art_painting/dog/pic_046.jpg 1 +art_painting/dog/pic_075.jpg 1 +art_painting/dog/pic_076.jpg 1 +art_painting/dog/pic_090.jpg 1 +art_painting/dog/pic_097.jpg 1 +art_painting/dog/pic_099.jpg 1 +art_painting/dog/pic_061.jpg 1 +art_painting/dog/pic_058.jpg 1 +art_painting/dog/pic_056.jpg 1 +art_painting/dog/pic_063.jpg 1 +art_painting/dog/pic_057.jpg 1 +art_painting/dog/pic_060.jpg 1 +art_painting/dog/pic_059.jpg 1 +art_painting/dog/pic_104.jpg 1 +art_painting/dog/pic_108.jpg 1 +art_painting/dog/pic_173.jpg 1 +art_painting/dog/pic_174.jpg 1 +art_painting/dog/pic_254.jpg 1 +art_painting/dog/pic_184.jpg 1 +art_painting/dog/pic_191.jpg 1 +art_painting/dog/pic_194.jpg 1 +art_painting/dog/pic_189.jpg 1 +art_painting/dog/pic_262.jpg 1 +art_painting/dog/pic_195.jpg 1 +art_painting/dog/pic_214.jpg 1 +art_painting/dog/pic_213.jpg 1 +art_painting/dog/pic_263.jpg 1 +art_painting/dog/pic_264.jpg 1 +art_painting/dog/pic_186.jpg 1 +art_painting/dog/pic_168.jpg 1 +art_painting/dog/pic_206.jpg 1 +art_painting/dog/pic_202.jpg 1 +art_painting/dog/pic_180.jpg 1 +art_painting/dog/pic_204.jpg 1 +art_painting/dog/pic_154.jpg 1 +art_painting/dog/pic_072.jpg 1 +art_painting/dog/pic_074.jpg 1 +art_painting/dog/pic_073.jpg 1 +art_painting/dog/pic_086.jpg 1 +art_painting/dog/pic_082.jpg 1 +art_painting/dog/pic_067.jpg 1 +art_painting/dog/pic_158.jpg 1 +art_painting/dog/pic_079.jpg 1 +art_painting/dog/pic_077.jpg 1 +art_painting/dog/pic_161.jpg 1 +art_painting/dog/pic_096.jpg 1 +art_painting/dog/pic_095.jpg 1 +art_painting/dog/pic_080.jpg 1 +art_painting/dog/pic_100.jpg 1 +art_painting/dog/pic_102.jpg 1 +art_painting/dog/pic_091.jpg 1 +art_painting/dog/pic_135.jpg 1 +art_painting/dog/pic_033.jpg 1 +art_painting/dog/pic_034.jpg 1 +art_painting/dog/pic_024.jpg 1 +art_painting/dog/pic_021.jpg 1 +art_painting/dog/pic_027.jpg 1 +art_painting/dog/pic_035.jpg 1 +art_painting/dog/pic_037.jpg 1 +art_painting/dog/pic_039.jpg 1 +art_painting/dog/pic_036.jpg 1 +art_painting/dog/pic_041.jpg 1 +art_painting/dog/pic_042.jpg 1 +art_painting/dog/pic_038.jpg 1 +art_painting/dog/pic_045.jpg 1 +art_painting/dog/pic_043.jpg 1 +art_painting/dog/pic_044.jpg 1 +art_painting/dog/pic_049.jpg 1 +art_painting/dog/pic_040.jpg 1 +art_painting/dog/pic_051.jpg 1 +art_painting/dog/pic_054.jpg 1 +art_painting/dog/pic_053.jpg 1 +art_painting/dog/pic_344.jpg 1 +art_painting/dog/pic_328.jpg 1 +art_painting/dog/pic_321.jpg 1 +art_painting/dog/pic_320.jpg 1 +art_painting/dog/pic_326.jpg 1 +art_painting/dog/pic_327.jpg 1 +art_painting/dog/pic_318.jpg 1 +art_painting/dog/pic_387.jpg 1 +art_painting/dog/pic_319.jpg 1 +art_painting/dog/pic_341.jpg 1 +art_painting/dog/pic_331.jpg 1 +art_painting/dog/pic_337.jpg 1 +art_painting/dog/pic_335.jpg 1 +art_painting/dog/pic_338.jpg 1 +art_painting/dog/pic_336.jpg 1 +art_painting/dog/pic_353.jpg 1 +art_painting/dog/pic_352.jpg 1 +art_painting/dog/pic_397.jpg 1 +art_painting/dog/pic_345.jpg 1 +art_painting/dog/pic_398.jpg 1 +art_painting/dog/pic_098.jpg 1 +art_painting/dog/pic_094.jpg 1 +art_painting/dog/pic_081.jpg 1 +art_painting/dog/pic_101.jpg 1 +art_painting/dog/pic_078.jpg 1 +art_painting/dog/pic_084.jpg 1 +art_painting/dog/pic_211.jpg 1 +art_painting/dog/pic_138.jpg 1 +art_painting/dog/pic_155.jpg 1 +art_painting/dog/pic_156.jpg 1 +art_painting/dog/pic_157.jpg 1 +art_painting/dog/pic_222.jpg 1 +art_painting/dog/pic_217.jpg 1 +art_painting/dog/pic_223.jpg 1 +art_painting/dog/pic_229.jpg 1 +art_painting/dog/pic_134.jpg 1 +art_painting/dog/pic_117.jpg 1 +art_painting/dog/pic_235.jpg 1 +art_painting/dog/pic_200.jpg 1 +art_painting/dog/pic_245.jpg 1 +art_painting/dog/pic_285.jpg 1 +art_painting/dog/pic_212.jpg 1 +art_painting/dog/pic_197.jpg 1 +art_painting/dog/pic_294.jpg 1 +art_painting/dog/pic_215.jpg 1 +art_painting/dog/pic_203.jpg 1 +art_painting/dog/pic_297.jpg 1 +art_painting/dog/pic_231.jpg 1 +art_painting/dog/pic_233.jpg 1 +art_painting/dog/pic_224.jpg 1 +art_painting/dog/pic_227.jpg 1 +art_painting/dog/pic_230.jpg 1 +art_painting/dog/pic_228.jpg 1 +art_painting/dog/pic_232.jpg 1 +art_painting/dog/pic_238.jpg 1 +art_painting/dog/pic_220.jpg 1 +art_painting/dog/pic_304.jpg 1 +art_painting/elephant/pic_085.jpg 2 +art_painting/elephant/pic_090.jpg 2 +art_painting/elephant/pic_089.jpg 2 +art_painting/elephant/pic_099.jpg 2 +art_painting/elephant/pic_111.jpg 2 +art_painting/elephant/pic_108.jpg 2 +art_painting/elephant/pic_114.jpg 2 +art_painting/elephant/pic_116.jpg 2 +art_painting/elephant/pic_123.jpg 2 +art_painting/elephant/pic_133.jpg 2 +art_painting/elephant/pic_131.jpg 2 +art_painting/elephant/pic_122.jpg 2 +art_painting/elephant/pic_113.jpg 2 +art_painting/elephant/pic_115.jpg 2 +art_painting/elephant/pic_112.jpg 2 +art_painting/elephant/pic_251.jpg 2 +art_painting/elephant/pic_250.jpg 2 +art_painting/elephant/pic_242.jpg 2 +art_painting/elephant/pic_246.jpg 2 +art_painting/elephant/pic_257.jpg 2 +art_painting/elephant/pic_249.jpg 2 +art_painting/elephant/pic_261.jpg 2 +art_painting/elephant/pic_260.jpg 2 +art_painting/elephant/pic_259.jpg 2 +art_painting/elephant/pic_039.jpg 2 +art_painting/elephant/pic_033.jpg 2 +art_painting/elephant/pic_041.jpg 2 +art_painting/elephant/pic_049.jpg 2 +art_painting/elephant/pic_048.jpg 2 +art_painting/elephant/pic_030.jpg 2 +art_painting/elephant/pic_026.jpg 2 +art_painting/elephant/pic_052.jpg 2 +art_painting/elephant/pic_053.jpg 2 +art_painting/elephant/pic_050.jpg 2 +art_painting/elephant/pic_054.jpg 2 +art_painting/elephant/pic_058.jpg 2 +art_painting/elephant/pic_056.jpg 2 +art_painting/elephant/pic_057.jpg 2 +art_painting/elephant/pic_055.jpg 2 +art_painting/elephant/pic_059.jpg 2 +art_painting/elephant/pic_060.jpg 2 +art_painting/elephant/pic_065.jpg 2 +art_painting/elephant/pic_063.jpg 2 +art_painting/elephant/pic_064.jpg 2 +art_painting/elephant/pic_061.jpg 2 +art_painting/elephant/pic_193.jpg 2 +art_painting/elephant/pic_192.jpg 2 +art_painting/elephant/pic_198.jpg 2 +art_painting/elephant/pic_201.jpg 2 +art_painting/elephant/pic_199.jpg 2 +art_painting/elephant/pic_212.jpg 2 +art_painting/elephant/pic_211.jpg 2 +art_painting/elephant/pic_210.jpg 2 +art_painting/elephant/pic_209.jpg 2 +art_painting/elephant/pic_208.jpg 2 +art_painting/elephant/pic_206.jpg 2 +art_painting/elephant/pic_207.jpg 2 +art_painting/elephant/pic_205.jpg 2 +art_painting/elephant/pic_203.jpg 2 +art_painting/elephant/pic_204.jpg 2 +art_painting/elephant/pic_222.jpg 2 +art_painting/elephant/pic_221.jpg 2 +art_painting/elephant/pic_218.jpg 2 +art_painting/elephant/pic_215.jpg 2 +art_painting/elephant/pic_213.jpg 2 +art_painting/elephant/pic_035.jpg 2 +art_painting/elephant/pic_036.jpg 2 +art_painting/elephant/pic_031.jpg 2 +art_painting/elephant/pic_034.jpg 2 +art_painting/elephant/pic_027.jpg 2 +art_painting/elephant/pic_040.jpg 2 +art_painting/elephant/pic_044.jpg 2 +art_painting/elephant/pic_043.jpg 2 +art_painting/elephant/pic_029.jpg 2 +art_painting/elephant/pic_023.jpg 2 +art_painting/elephant/pic_037.jpg 2 +art_painting/elephant/pic_045.jpg 2 +art_painting/elephant/pic_024.jpg 2 +art_painting/elephant/pic_046.jpg 2 +art_painting/elephant/pic_022.jpg 2 +art_painting/elephant/pic_047.jpg 2 +art_painting/elephant/pic_025.jpg 2 +art_painting/elephant/pic_021.jpg 2 +art_painting/elephant/pic_020.jpg 2 +art_painting/elephant/pic_174.jpg 2 +art_painting/elephant/pic_182.jpg 2 +art_painting/elephant/pic_181.jpg 2 +art_painting/elephant/pic_180.jpg 2 +art_painting/elephant/pic_178.jpg 2 +art_painting/elephant/pic_177.jpg 2 +art_painting/elephant/pic_188.jpg 2 +art_painting/elephant/pic_187.jpg 2 +art_painting/elephant/pic_185.jpg 2 +art_painting/elephant/pic_186.jpg 2 +art_painting/elephant/pic_184.jpg 2 +art_painting/elephant/pic_183.jpg 2 +art_painting/elephant/pic_191.jpg 2 +art_painting/elephant/pic_190.jpg 2 +art_painting/elephant/pic_189.jpg 2 +art_painting/elephant/pic_202.jpg 2 +art_painting/elephant/pic_200.jpg 2 +art_painting/elephant/pic_196.jpg 2 +art_painting/elephant/pic_197.jpg 2 +art_painting/elephant/pic_194.jpg 2 +art_painting/elephant/pic_195.jpg 2 +art_painting/elephant/pic_110.jpg 2 +art_painting/elephant/pic_106.jpg 2 +art_painting/elephant/pic_105.jpg 2 +art_painting/elephant/pic_102.jpg 2 +art_painting/elephant/pic_101.jpg 2 +art_painting/elephant/pic_100.jpg 2 +art_painting/elephant/pic_097.jpg 2 +art_painting/elephant/pic_095.jpg 2 +art_painting/elephant/pic_096.jpg 2 +art_painting/elephant/pic_127.jpg 2 +art_painting/elephant/pic_150.jpg 2 +art_painting/elephant/pic_130.jpg 2 +art_painting/elephant/pic_119.jpg 2 +art_painting/elephant/pic_109.jpg 2 +art_painting/elephant/pic_104.jpg 2 +art_painting/elephant/pic_129.jpg 2 +art_painting/elephant/pic_128.jpg 2 +art_painting/elephant/pic_103.jpg 2 +art_painting/elephant/pic_098.jpg 2 +art_painting/elephant/pic_214.jpg 2 +art_painting/elephant/pic_217.jpg 2 +art_painting/elephant/pic_232.jpg 2 +art_painting/elephant/pic_231.jpg 2 +art_painting/elephant/pic_230.jpg 2 +art_painting/elephant/pic_229.jpg 2 +art_painting/elephant/pic_226.jpg 2 +art_painting/elephant/pic_224.jpg 2 +art_painting/elephant/pic_225.jpg 2 +art_painting/elephant/pic_223.jpg 2 +art_painting/elephant/pic_227.jpg 2 +art_painting/elephant/pic_228.jpg 2 +art_painting/elephant/pic_235.jpg 2 +art_painting/elephant/pic_236.jpg 2 +art_painting/elephant/pic_234.jpg 2 +art_painting/elephant/pic_241.jpg 2 +art_painting/elephant/pic_258.jpg 2 +art_painting/elephant/pic_256.jpg 2 +art_painting/elephant/pic_254.jpg 2 +art_painting/elephant/pic_255.jpg 2 +art_painting/elephant/pic_253.jpg 2 +art_painting/elephant/pic_004.jpg 2 +art_painting/elephant/pic_005.jpg 2 +art_painting/elephant/pic_006.jpg 2 +art_painting/elephant/pic_007.jpg 2 +art_painting/elephant/pic_008.jpg 2 +art_painting/elephant/pic_009.jpg 2 +art_painting/elephant/pic_010.jpg 2 +art_painting/elephant/pic_011.jpg 2 +art_painting/elephant/pic_012.jpg 2 +art_painting/elephant/pic_014.jpg 2 +art_painting/elephant/pic_015.jpg 2 +art_painting/elephant/pic_016.jpg 2 +art_painting/elephant/pic_017.jpg 2 +art_painting/elephant/pic_018.jpg 2 +art_painting/elephant/pic_019.jpg 2 +art_painting/elephant/pic_051.jpg 2 +art_painting/elephant/pic_042.jpg 2 +art_painting/elephant/pic_028.jpg 2 +art_painting/elephant/pic_032.jpg 2 +art_painting/elephant/pic_001.jpg 2 +art_painting/elephant/pic_002.jpg 2 +art_painting/elephant/pic_003.jpg 2 +art_painting/elephant/pic_107.jpg 2 +art_painting/elephant/pic_117.jpg 2 +art_painting/elephant/pic_120.jpg 2 +art_painting/elephant/pic_118.jpg 2 +art_painting/elephant/pic_121.jpg 2 +art_painting/elephant/pic_125.jpg 2 +art_painting/elephant/pic_124.jpg 2 +art_painting/elephant/pic_126.jpg 2 +art_painting/elephant/pic_132.jpg 2 +art_painting/elephant/pic_151.jpg 2 +art_painting/elephant/pic_138.jpg 2 +art_painting/elephant/pic_139.jpg 2 +art_painting/elephant/pic_136.jpg 2 +art_painting/elephant/pic_137.jpg 2 +art_painting/elephant/pic_179.jpg 2 +art_painting/elephant/pic_134.jpg 2 +art_painting/elephant/pic_164.jpg 2 +art_painting/elephant/pic_163.jpg 2 +art_painting/elephant/pic_135.jpg 2 +art_painting/elephant/pic_165.jpg 2 +art_painting/elephant/pic_219.jpg 2 +art_painting/elephant/pic_062.jpg 2 +art_painting/elephant/pic_066.jpg 2 +art_painting/elephant/pic_067.jpg 2 +art_painting/elephant/pic_068.jpg 2 +art_painting/elephant/pic_069.jpg 2 +art_painting/elephant/pic_070.jpg 2 +art_painting/elephant/pic_071.jpg 2 +art_painting/elephant/pic_072.jpg 2 +art_painting/elephant/pic_073.jpg 2 +art_painting/elephant/pic_074.jpg 2 +art_painting/elephant/pic_075.jpg 2 +art_painting/elephant/pic_076.jpg 2 +art_painting/elephant/pic_077.jpg 2 +art_painting/elephant/pic_094.jpg 2 +art_painting/elephant/pic_092.jpg 2 +art_painting/elephant/pic_091.jpg 2 +art_painting/elephant/pic_088.jpg 2 +art_painting/elephant/pic_087.jpg 2 +art_painting/elephant/pic_086.jpg 2 +art_painting/elephant/pic_084.jpg 2 +art_painting/elephant/pic_083.jpg 2 +art_painting/elephant/pic_146.jpg 2 +art_painting/elephant/pic_142.jpg 2 +art_painting/elephant/pic_144.jpg 2 +art_painting/elephant/pic_143.jpg 2 +art_painting/elephant/pic_140.jpg 2 +art_painting/elephant/pic_141.jpg 2 +art_painting/elephant/pic_145.jpg 2 +art_painting/elephant/pic_149.jpg 2 +art_painting/elephant/pic_233.jpg 2 +art_painting/elephant/pic_148.jpg 2 +art_painting/elephant/pic_147.jpg 2 +art_painting/elephant/pic_220.jpg 2 +art_painting/elephant/pic_153.jpg 2 +art_painting/elephant/pic_237.jpg 2 +art_painting/elephant/pic_152.jpg 2 +art_painting/elephant/pic_238.jpg 2 +art_painting/elephant/pic_155.jpg 2 +art_painting/elephant/pic_252.jpg 2 +art_painting/elephant/pic_244.jpg 2 +art_painting/elephant/pic_240.jpg 2 +art_painting/giraffe/pic_308.jpg 3 +art_painting/giraffe/pic_307.jpg 3 +art_painting/giraffe/pic_276.jpg 3 +art_painting/giraffe/pic_298.jpg 3 +art_painting/giraffe/pic_244.jpg 3 +art_painting/giraffe/pic_242.jpg 3 +art_painting/giraffe/pic_240.jpg 3 +art_painting/giraffe/pic_234.jpg 3 +art_painting/giraffe/pic_206.jpg 3 +art_painting/giraffe/pic_204.jpg 3 +art_painting/giraffe/pic_193.jpg 3 +art_painting/giraffe/pic_190.jpg 3 +art_painting/giraffe/pic_188.jpg 3 +art_painting/giraffe/pic_186.jpg 3 +art_painting/giraffe/pic_280.jpg 3 +art_painting/giraffe/pic_177.jpg 3 +art_painting/giraffe/pic_264.jpg 3 +art_painting/giraffe/pic_263.jpg 3 +art_painting/giraffe/pic_282.jpg 3 +art_painting/giraffe/pic_077.jpg 3 +art_painting/giraffe/pic_075.jpg 3 +art_painting/giraffe/pic_083.jpg 3 +art_painting/giraffe/pic_090.jpg 3 +art_painting/giraffe/pic_089.jpg 3 +art_painting/giraffe/pic_088.jpg 3 +art_painting/giraffe/pic_087.jpg 3 +art_painting/giraffe/pic_086.jpg 3 +art_painting/giraffe/pic_085.jpg 3 +art_painting/giraffe/pic_084.jpg 3 +art_painting/giraffe/pic_092.jpg 3 +art_painting/giraffe/pic_091.jpg 3 +art_painting/giraffe/pic_097.jpg 3 +art_painting/giraffe/pic_096.jpg 3 +art_painting/giraffe/pic_095.jpg 3 +art_painting/giraffe/pic_093.jpg 3 +art_painting/giraffe/pic_094.jpg 3 +art_painting/giraffe/pic_100.jpg 3 +art_painting/giraffe/pic_107.jpg 3 +art_painting/giraffe/pic_106.jpg 3 +art_painting/giraffe/pic_247.jpg 3 +art_painting/giraffe/pic_252.jpg 3 +art_painting/giraffe/pic_266.jpg 3 +art_painting/giraffe/pic_246.jpg 3 +art_painting/giraffe/pic_241.jpg 3 +art_painting/giraffe/pic_248.jpg 3 +art_painting/giraffe/pic_271.jpg 3 +art_painting/giraffe/pic_283.jpg 3 +art_painting/giraffe/pic_258.jpg 3 +art_painting/giraffe/pic_279.jpg 3 +art_painting/giraffe/pic_297.jpg 3 +art_painting/giraffe/pic_300.jpg 3 +art_painting/giraffe/pic_257.jpg 3 +art_painting/giraffe/pic_249.jpg 3 +art_painting/giraffe/pic_254.jpg 3 +art_painting/giraffe/pic_253.jpg 3 +art_painting/giraffe/pic_245.jpg 3 +art_painting/giraffe/pic_236.jpg 3 +art_painting/giraffe/pic_164.jpg 3 +art_painting/giraffe/pic_166.jpg 3 +art_painting/giraffe/pic_200.jpg 3 +art_painting/giraffe/pic_147.jpg 3 +art_painting/giraffe/pic_210.jpg 3 +art_painting/giraffe/pic_170.jpg 3 +art_painting/giraffe/pic_168.jpg 3 +art_painting/giraffe/pic_223.jpg 3 +art_painting/giraffe/pic_213.jpg 3 +art_painting/giraffe/pic_207.jpg 3 +art_painting/giraffe/pic_171.jpg 3 +art_painting/giraffe/pic_232.jpg 3 +art_painting/giraffe/pic_211.jpg 3 +art_painting/giraffe/pic_221.jpg 3 +art_painting/giraffe/pic_230.jpg 3 +art_painting/giraffe/pic_235.jpg 3 +art_painting/giraffe/pic_212.jpg 3 +art_painting/giraffe/pic_231.jpg 3 +art_painting/giraffe/pic_021.jpg 3 +art_painting/giraffe/pic_033.jpg 3 +art_painting/giraffe/pic_050.jpg 3 +art_painting/giraffe/pic_046.jpg 3 +art_painting/giraffe/pic_045.jpg 3 +art_painting/giraffe/pic_030.jpg 3 +art_painting/giraffe/pic_037.jpg 3 +art_painting/giraffe/pic_024.jpg 3 +art_painting/giraffe/pic_042.jpg 3 +art_painting/giraffe/pic_028.jpg 3 +art_painting/giraffe/pic_051.jpg 3 +art_painting/giraffe/pic_025.jpg 3 +art_painting/giraffe/pic_043.jpg 3 +art_painting/giraffe/pic_052.jpg 3 +art_painting/giraffe/pic_049.jpg 3 +art_painting/giraffe/pic_044.jpg 3 +art_painting/giraffe/pic_023.jpg 3 +art_painting/giraffe/pic_053.jpg 3 +art_painting/giraffe/pic_056.jpg 3 +art_painting/giraffe/pic_068.jpg 3 +art_painting/giraffe/pic_063.jpg 3 +art_painting/giraffe/pic_182.jpg 3 +art_painting/giraffe/pic_173.jpg 3 +art_painting/giraffe/pic_165.jpg 3 +art_painting/giraffe/pic_154.jpg 3 +art_painting/giraffe/pic_138.jpg 3 +art_painting/giraffe/pic_137.jpg 3 +art_painting/giraffe/pic_136.jpg 3 +art_painting/giraffe/pic_062.jpg 3 +art_painting/giraffe/pic_061.jpg 3 +art_painting/giraffe/pic_059.jpg 3 +art_painting/giraffe/pic_060.jpg 3 +art_painting/giraffe/pic_058.jpg 3 +art_painting/giraffe/pic_057.jpg 3 +art_painting/giraffe/pic_069.jpg 3 +art_painting/giraffe/pic_066.jpg 3 +art_painting/giraffe/pic_065.jpg 3 +art_painting/giraffe/pic_070.jpg 3 +art_painting/giraffe/pic_072.jpg 3 +art_painting/giraffe/pic_071.jpg 3 +art_painting/giraffe/pic_074.jpg 3 +art_painting/giraffe/pic_073.jpg 3 +art_painting/giraffe/pic_081.jpg 3 +art_painting/giraffe/pic_082.jpg 3 +art_painting/giraffe/pic_080.jpg 3 +art_painting/giraffe/pic_078.jpg 3 +art_painting/giraffe/pic_079.jpg 3 +art_painting/giraffe/pic_001.jpg 3 +art_painting/giraffe/pic_002.jpg 3 +art_painting/giraffe/pic_003.jpg 3 +art_painting/giraffe/pic_004.jpg 3 +art_painting/giraffe/pic_005.jpg 3 +art_painting/giraffe/pic_007.jpg 3 +art_painting/giraffe/pic_008.jpg 3 +art_painting/giraffe/pic_009.jpg 3 +art_painting/giraffe/pic_010.jpg 3 +art_painting/giraffe/pic_011.jpg 3 +art_painting/giraffe/pic_012.jpg 3 +art_painting/giraffe/pic_013.jpg 3 +art_painting/giraffe/pic_014.jpg 3 +art_painting/giraffe/pic_015.jpg 3 +art_painting/giraffe/pic_016.jpg 3 +art_painting/giraffe/pic_140.jpg 3 +art_painting/giraffe/pic_150.jpg 3 +art_painting/giraffe/pic_159.jpg 3 +art_painting/giraffe/pic_135.jpg 3 +art_painting/giraffe/pic_224.jpg 3 +art_painting/giraffe/pic_153.jpg 3 +art_painting/giraffe/pic_227.jpg 3 +art_painting/giraffe/pic_226.jpg 3 +art_painting/giraffe/pic_162.jpg 3 +art_painting/giraffe/pic_175.jpg 3 +art_painting/giraffe/pic_225.jpg 3 +art_painting/giraffe/pic_229.jpg 3 +art_painting/giraffe/pic_167.jpg 3 +art_painting/giraffe/pic_174.jpg 3 +art_painting/giraffe/pic_161.jpg 3 +art_painting/giraffe/pic_184.jpg 3 +art_painting/giraffe/pic_141.jpg 3 +art_painting/giraffe/pic_201.jpg 3 +art_painting/giraffe/pic_237.jpg 3 +art_painting/giraffe/pic_163.jpg 3 +art_painting/giraffe/pic_133.jpg 3 +art_painting/giraffe/pic_132.jpg 3 +art_painting/giraffe/pic_130.jpg 3 +art_painting/giraffe/pic_125.jpg 3 +art_painting/giraffe/pic_123.jpg 3 +art_painting/giraffe/pic_121.jpg 3 +art_painting/giraffe/pic_122.jpg 3 +art_painting/giraffe/pic_119.jpg 3 +art_painting/giraffe/pic_120.jpg 3 +art_painting/giraffe/pic_118.jpg 3 +art_painting/giraffe/pic_208.jpg 3 +art_painting/giraffe/pic_217.jpg 3 +art_painting/giraffe/pic_172.jpg 3 +art_painting/giraffe/pic_157.jpg 3 +art_painting/giraffe/pic_152.jpg 3 +art_painting/giraffe/pic_143.jpg 3 +art_painting/giraffe/pic_176.jpg 3 +art_painting/giraffe/pic_146.jpg 3 +art_painting/giraffe/pic_139.jpg 3 +art_painting/giraffe/pic_142.jpg 3 +art_painting/giraffe/pic_105.jpg 3 +art_painting/giraffe/pic_104.jpg 3 +art_painting/giraffe/pic_102.jpg 3 +art_painting/giraffe/pic_101.jpg 3 +art_painting/giraffe/pic_099.jpg 3 +art_painting/giraffe/pic_098.jpg 3 +art_painting/giraffe/pic_103.jpg 3 +art_painting/giraffe/pic_115.jpg 3 +art_painting/giraffe/pic_117.jpg 3 +art_painting/giraffe/pic_116.jpg 3 +art_painting/giraffe/pic_110.jpg 3 +art_painting/giraffe/pic_113.jpg 3 +art_painting/giraffe/pic_111.jpg 3 +art_painting/giraffe/pic_112.jpg 3 +art_painting/giraffe/pic_109.jpg 3 +art_painting/giraffe/pic_108.jpg 3 +art_painting/giraffe/pic_114.jpg 3 +art_painting/giraffe/pic_126.jpg 3 +art_painting/giraffe/pic_128.jpg 3 +art_painting/giraffe/pic_218.jpg 3 +art_painting/giraffe/pic_178.jpg 3 +art_painting/giraffe/pic_191.jpg 3 +art_painting/giraffe/pic_285.jpg 3 +art_painting/giraffe/pic_270.jpg 3 +art_painting/giraffe/pic_267.jpg 3 +art_painting/giraffe/pic_288.jpg 3 +art_painting/giraffe/pic_261.jpg 3 +art_painting/giraffe/pic_305.jpg 3 +art_painting/giraffe/pic_274.jpg 3 +art_painting/giraffe/pic_251.jpg 3 +art_painting/giraffe/pic_291.jpg 3 +art_painting/giraffe/pic_259.jpg 3 +art_painting/giraffe/pic_262.jpg 3 +art_painting/giraffe/pic_304.jpg 3 +art_painting/giraffe/pic_268.jpg 3 +art_painting/giraffe/pic_256.jpg 3 +art_painting/giraffe/pic_281.jpg 3 +art_painting/giraffe/pic_292.jpg 3 +art_painting/giraffe/pic_293.jpg 3 +art_painting/giraffe/pic_277.jpg 3 +art_painting/giraffe/pic_017.jpg 3 +art_painting/giraffe/pic_018.jpg 3 +art_painting/giraffe/pic_019.jpg 3 +art_painting/giraffe/pic_022.jpg 3 +art_painting/giraffe/pic_027.jpg 3 +art_painting/giraffe/pic_034.jpg 3 +art_painting/giraffe/pic_035.jpg 3 +art_painting/giraffe/pic_029.jpg 3 +art_painting/giraffe/pic_055.jpg 3 +art_painting/giraffe/pic_054.jpg 3 +art_painting/giraffe/pic_048.jpg 3 +art_painting/giraffe/pic_047.jpg 3 +art_painting/giraffe/pic_031.jpg 3 +art_painting/giraffe/pic_032.jpg 3 +art_painting/giraffe/pic_041.jpg 3 +art_painting/giraffe/pic_036.jpg 3 +art_painting/giraffe/pic_040.jpg 3 +art_painting/giraffe/pic_038.jpg 3 +art_painting/giraffe/pic_039.jpg 3 +art_painting/giraffe/pic_020.jpg 3 +art_painting/giraffe/pic_026.jpg 3 +art_painting/giraffe/pic_243.jpg 3 +art_painting/giraffe/pic_278.jpg 3 +art_painting/giraffe/pic_272.jpg 3 +art_painting/giraffe/pic_306.jpg 3 +art_painting/giraffe/pic_290.jpg 3 +art_painting/giraffe/pic_265.jpg 3 +art_painting/giraffe/pic_255.jpg 3 +art_painting/giraffe/pic_194.jpg 3 +art_painting/giraffe/pic_216.jpg 3 +art_painting/giraffe/pic_215.jpg 3 +art_painting/giraffe/pic_233.jpg 3 +art_painting/giraffe/pic_203.jpg 3 +art_painting/giraffe/pic_192.jpg 3 +art_painting/giraffe/pic_214.jpg 3 +art_painting/giraffe/pic_239.jpg 3 +art_painting/giraffe/pic_205.jpg 3 +art_painting/giraffe/pic_180.jpg 3 +art_painting/giraffe/pic_195.jpg 3 +art_painting/guitar/pic_055.jpg 4 +art_painting/guitar/pic_059.jpg 4 +art_painting/guitar/pic_061.jpg 4 +art_painting/guitar/pic_060.jpg 4 +art_painting/guitar/pic_062.jpg 4 +art_painting/guitar/pic_063.jpg 4 +art_painting/guitar/pic_064.jpg 4 +art_painting/guitar/pic_067.jpg 4 +art_painting/guitar/pic_069.jpg 4 +art_painting/guitar/pic_077.jpg 4 +art_painting/guitar/pic_076.jpg 4 +art_painting/guitar/pic_075.jpg 4 +art_painting/guitar/pic_073.jpg 4 +art_painting/guitar/pic_072.jpg 4 +art_painting/guitar/pic_071.jpg 4 +art_painting/guitar/pic_070.jpg 4 +art_painting/guitar/pic_078.jpg 4 +art_painting/guitar/pic_111.jpg 4 +art_painting/guitar/pic_101.jpg 4 +art_painting/guitar/pic_130.jpg 4 +art_painting/guitar/pic_113.jpg 4 +art_painting/guitar/pic_182.jpg 4 +art_painting/guitar/pic_115.jpg 4 +art_painting/guitar/pic_100.jpg 4 +art_painting/guitar/pic_104.jpg 4 +art_painting/guitar/pic_098.jpg 4 +art_painting/guitar/pic_155.jpg 4 +art_painting/guitar/pic_149.jpg 4 +art_painting/guitar/pic_144.jpg 4 +art_painting/guitar/pic_143.jpg 4 +art_painting/guitar/pic_120.jpg 4 +art_painting/guitar/pic_152.jpg 4 +art_painting/guitar/pic_170.jpg 4 +art_painting/guitar/pic_157.jpg 4 +art_painting/guitar/pic_107.jpg 4 +art_painting/guitar/pic_173.jpg 4 +art_painting/guitar/pic_128.jpg 4 +art_painting/guitar/pic_074.jpg 4 +art_painting/guitar/pic_088.jpg 4 +art_painting/guitar/pic_087.jpg 4 +art_painting/guitar/pic_086.jpg 4 +art_painting/guitar/pic_084.jpg 4 +art_painting/guitar/pic_082.jpg 4 +art_painting/guitar/pic_083.jpg 4 +art_painting/guitar/pic_081.jpg 4 +art_painting/guitar/pic_079.jpg 4 +art_painting/guitar/pic_080.jpg 4 +art_painting/guitar/pic_089.jpg 4 +art_painting/guitar/pic_085.jpg 4 +art_painting/guitar/pic_142.jpg 4 +art_painting/guitar/pic_134.jpg 4 +art_painting/guitar/pic_133.jpg 4 +art_painting/guitar/pic_129.jpg 4 +art_painting/guitar/pic_127.jpg 4 +art_painting/guitar/pic_118.jpg 4 +art_painting/guitar/pic_109.jpg 4 +art_painting/guitar/pic_106.jpg 4 +art_painting/guitar/pic_103.jpg 4 +art_painting/guitar/pic_001.jpg 4 +art_painting/guitar/pic_002.jpg 4 +art_painting/guitar/pic_003.jpg 4 +art_painting/guitar/pic_004.jpg 4 +art_painting/guitar/pic_005.jpg 4 +art_painting/guitar/pic_006.jpg 4 +art_painting/guitar/pic_007.jpg 4 +art_painting/guitar/pic_008.jpg 4 +art_painting/guitar/pic_009.jpg 4 +art_painting/guitar/pic_010.jpg 4 +art_painting/guitar/pic_011.jpg 4 +art_painting/guitar/pic_012.jpg 4 +art_painting/guitar/pic_013.jpg 4 +art_painting/guitar/pic_014.jpg 4 +art_painting/guitar/pic_015.jpg 4 +art_painting/guitar/pic_020.jpg 4 +art_painting/guitar/pic_018.jpg 4 +art_painting/guitar/pic_017.jpg 4 +art_painting/guitar/pic_016.jpg 4 +art_painting/guitar/pic_026.jpg 4 +art_painting/guitar/pic_025.jpg 4 +art_painting/guitar/pic_024.jpg 4 +art_painting/guitar/pic_023.jpg 4 +art_painting/guitar/pic_021.jpg 4 +art_painting/guitar/pic_019.jpg 4 +art_painting/guitar/pic_022.jpg 4 +art_painting/guitar/pic_028.jpg 4 +art_painting/guitar/pic_027.jpg 4 +art_painting/guitar/pic_035.jpg 4 +art_painting/guitar/pic_047.jpg 4 +art_painting/guitar/pic_042.jpg 4 +art_painting/guitar/pic_043.jpg 4 +art_painting/guitar/pic_041.jpg 4 +art_painting/guitar/pic_040.jpg 4 +art_painting/guitar/pic_038.jpg 4 +art_painting/guitar/pic_037.jpg 4 +art_painting/guitar/pic_036.jpg 4 +art_painting/guitar/pic_034.jpg 4 +art_painting/guitar/pic_032.jpg 4 +art_painting/guitar/pic_031.jpg 4 +art_painting/guitar/pic_029.jpg 4 +art_painting/guitar/pic_044.jpg 4 +art_painting/guitar/pic_039.jpg 4 +art_painting/guitar/pic_048.jpg 4 +art_painting/guitar/pic_030.jpg 4 +art_painting/guitar/pic_049.jpg 4 +art_painting/guitar/pic_033.jpg 4 +art_painting/guitar/pic_053.jpg 4 +art_painting/guitar/pic_052.jpg 4 +art_painting/guitar/pic_051.jpg 4 +art_painting/guitar/pic_050.jpg 4 +art_painting/guitar/pic_058.jpg 4 +art_painting/guitar/pic_056.jpg 4 +art_painting/guitar/pic_175.jpg 4 +art_painting/guitar/pic_167.jpg 4 +art_painting/guitar/pic_196.jpg 4 +art_painting/guitar/pic_197.jpg 4 +art_painting/guitar/pic_199.jpg 4 +art_painting/guitar/pic_192.jpg 4 +art_painting/guitar/pic_194.jpg 4 +art_painting/guitar/pic_190.jpg 4 +art_painting/guitar/pic_189.jpg 4 +art_painting/guitar/pic_188.jpg 4 +art_painting/guitar/pic_195.jpg 4 +art_painting/guitar/pic_201.jpg 4 +art_painting/guitar/pic_191.jpg 4 +art_painting/guitar/pic_193.jpg 4 +art_painting/guitar/pic_131.jpg 4 +art_painting/guitar/pic_114.jpg 4 +art_painting/guitar/pic_141.jpg 4 +art_painting/guitar/pic_105.jpg 4 +art_painting/guitar/pic_117.jpg 4 +art_painting/guitar/pic_178.jpg 4 +art_painting/guitar/pic_171.jpg 4 +art_painting/guitar/pic_169.jpg 4 +art_painting/guitar/pic_156.jpg 4 +art_painting/guitar/pic_148.jpg 4 +art_painting/guitar/pic_123.jpg 4 +art_painting/guitar/pic_163.jpg 4 +art_painting/guitar/pic_110.jpg 4 +art_painting/guitar/pic_138.jpg 4 +art_painting/guitar/pic_116.jpg 4 +art_painting/guitar/pic_145.jpg 4 +art_painting/guitar/pic_121.jpg 4 +art_painting/guitar/pic_160.jpg 4 +art_painting/guitar/pic_177.jpg 4 +art_painting/guitar/pic_166.jpg 4 +art_painting/guitar/pic_159.jpg 4 +art_painting/guitar/pic_102.jpg 4 +art_painting/guitar/pic_099.jpg 4 +art_painting/guitar/pic_097.jpg 4 +art_painting/guitar/pic_095.jpg 4 +art_painting/guitar/pic_092.jpg 4 +art_painting/guitar/pic_094.jpg 4 +art_painting/guitar/pic_093.jpg 4 +art_painting/guitar/pic_091.jpg 4 +art_painting/guitar/pic_090.jpg 4 +art_painting/guitar/pic_140.jpg 4 +art_painting/guitar/pic_153.jpg 4 +art_painting/guitar/pic_158.jpg 4 +art_painting/guitar/pic_132.jpg 4 +art_painting/guitar/pic_135.jpg 4 +art_painting/guitar/pic_119.jpg 4 +art_painting/guitar/pic_122.jpg 4 +art_painting/guitar/pic_108.jpg 4 +art_painting/guitar/pic_136.jpg 4 +art_painting/guitar/pic_112.jpg 4 +art_painting/horse/pic_005.jpg 5 +art_painting/horse/pic_096.jpg 5 +art_painting/horse/pic_103.jpg 5 +art_painting/horse/pic_110.jpg 5 +art_painting/horse/pic_098.jpg 5 +art_painting/horse/pic_116.jpg 5 +art_painting/horse/pic_120.jpg 5 +art_painting/horse/pic_112.jpg 5 +art_painting/horse/pic_106.jpg 5 +art_painting/horse/pic_123.jpg 5 +art_painting/horse/pic_117.jpg 5 +art_painting/horse/pic_181.jpg 5 +art_painting/horse/pic_141.jpg 5 +art_painting/horse/pic_145.jpg 5 +art_painting/horse/pic_139.jpg 5 +art_painting/horse/pic_138.jpg 5 +art_painting/horse/pic_137.jpg 5 +art_painting/horse/pic_134.jpg 5 +art_painting/horse/pic_135.jpg 5 +art_painting/horse/pic_073.jpg 5 +art_painting/horse/pic_071.jpg 5 +art_painting/horse/pic_072.jpg 5 +art_painting/horse/pic_076.jpg 5 +art_painting/horse/pic_079.jpg 5 +art_painting/horse/pic_081.jpg 5 +art_painting/horse/pic_078.jpg 5 +art_painting/horse/pic_074.jpg 5 +art_painting/horse/pic_077.jpg 5 +art_painting/horse/pic_080.jpg 5 +art_painting/horse/pic_109.jpg 5 +art_painting/horse/pic_104.jpg 5 +art_painting/horse/pic_101.jpg 5 +art_painting/horse/pic_100.jpg 5 +art_painting/horse/pic_097.jpg 5 +art_painting/horse/pic_089.jpg 5 +art_painting/horse/pic_090.jpg 5 +art_painting/horse/pic_091.jpg 5 +art_painting/horse/pic_088.jpg 5 +art_painting/horse/pic_087.jpg 5 +art_painting/horse/pic_083.jpg 5 +art_painting/horse/pic_047.jpg 5 +art_painting/horse/pic_048.jpg 5 +art_painting/horse/pic_049.jpg 5 +art_painting/horse/pic_050.jpg 5 +art_painting/horse/pic_006.jpg 5 +art_painting/horse/pic_007.jpg 5 +art_painting/horse/pic_008.jpg 5 +art_painting/horse/pic_010.jpg 5 +art_painting/horse/pic_011.jpg 5 +art_painting/horse/pic_012.jpg 5 +art_painting/horse/pic_014.jpg 5 +art_painting/horse/pic_015.jpg 5 +art_painting/horse/pic_017.jpg 5 +art_painting/horse/pic_027.jpg 5 +art_painting/horse/pic_019.jpg 5 +art_painting/horse/pic_032.jpg 5 +art_painting/horse/pic_035.jpg 5 +art_painting/horse/pic_024.jpg 5 +art_painting/horse/pic_036.jpg 5 +art_painting/horse/pic_031.jpg 5 +art_painting/horse/pic_160.jpg 5 +art_painting/horse/pic_169.jpg 5 +art_painting/horse/pic_184.jpg 5 +art_painting/horse/pic_179.jpg 5 +art_painting/horse/pic_177.jpg 5 +art_painting/horse/pic_178.jpg 5 +art_painting/horse/pic_176.jpg 5 +art_painting/horse/pic_172.jpg 5 +art_painting/horse/pic_174.jpg 5 +art_painting/horse/pic_173.jpg 5 +art_painting/horse/pic_171.jpg 5 +art_painting/horse/pic_186.jpg 5 +art_painting/horse/pic_199.jpg 5 +art_painting/horse/pic_198.jpg 5 +art_painting/horse/pic_197.jpg 5 +art_painting/horse/pic_191.jpg 5 +art_painting/horse/pic_189.jpg 5 +art_painting/horse/pic_053.jpg 5 +art_painting/horse/pic_051.jpg 5 +art_painting/horse/pic_054.jpg 5 +art_painting/horse/pic_052.jpg 5 +art_painting/horse/pic_057.jpg 5 +art_painting/horse/pic_056.jpg 5 +art_painting/horse/pic_059.jpg 5 +art_painting/horse/pic_060.jpg 5 +art_painting/horse/pic_062.jpg 5 +art_painting/horse/pic_063.jpg 5 +art_painting/horse/pic_061.jpg 5 +art_painting/horse/pic_067.jpg 5 +art_painting/horse/pic_069.jpg 5 +art_painting/horse/pic_066.jpg 5 +art_painting/horse/pic_064.jpg 5 +art_painting/horse/pic_065.jpg 5 +art_painting/horse/pic_070.jpg 5 +art_painting/horse/pic_075.jpg 5 +art_painting/horse/pic_086.jpg 5 +art_painting/horse/pic_082.jpg 5 +art_painting/horse/pic_105.jpg 5 +art_painting/horse/pic_108.jpg 5 +art_painting/horse/pic_107.jpg 5 +art_painting/horse/pic_084.jpg 5 +art_painting/horse/pic_093.jpg 5 +art_painting/horse/pic_099.jpg 5 +art_painting/horse/pic_092.jpg 5 +art_painting/horse/pic_095.jpg 5 +art_painting/horse/pic_121.jpg 5 +art_painting/horse/pic_114.jpg 5 +art_painting/horse/pic_085.jpg 5 +art_painting/horse/pic_113.jpg 5 +art_painting/horse/pic_122.jpg 5 +art_painting/horse/pic_115.jpg 5 +art_painting/horse/pic_102.jpg 5 +art_painting/horse/pic_119.jpg 5 +art_painting/horse/pic_227.jpg 5 +art_painting/horse/pic_226.jpg 5 +art_painting/horse/pic_224.jpg 5 +art_painting/horse/pic_223.jpg 5 +art_painting/horse/pic_222.jpg 5 +art_painting/horse/pic_220.jpg 5 +art_painting/horse/pic_218.jpg 5 +art_painting/horse/pic_217.jpg 5 +art_painting/horse/pic_228.jpg 5 +art_painting/horse/pic_221.jpg 5 +art_painting/horse/pic_219.jpg 5 +art_painting/horse/pic_232.jpg 5 +art_painting/horse/pic_229.jpg 5 +art_painting/horse/pic_193.jpg 5 +art_painting/horse/pic_192.jpg 5 +art_painting/horse/pic_196.jpg 5 +art_painting/horse/pic_200.jpg 5 +art_painting/horse/pic_208.jpg 5 +art_painting/horse/pic_206.jpg 5 +art_painting/horse/pic_203.jpg 5 +art_painting/horse/pic_202.jpg 5 +art_painting/horse/pic_201.jpg 5 +art_painting/horse/pic_209.jpg 5 +art_painting/horse/pic_207.jpg 5 +art_painting/horse/pic_205.jpg 5 +art_painting/horse/pic_210.jpg 5 +art_painting/horse/pic_215.jpg 5 +art_painting/horse/pic_216.jpg 5 +art_painting/horse/pic_212.jpg 5 +art_painting/horse/pic_213.jpg 5 +art_painting/horse/pic_214.jpg 5 +art_painting/horse/pic_225.jpg 5 +art_painting/horse/pic_133.jpg 5 +art_painting/horse/pic_131.jpg 5 +art_painting/horse/pic_125.jpg 5 +art_painting/horse/pic_127.jpg 5 +art_painting/horse/pic_126.jpg 5 +art_painting/horse/pic_156.jpg 5 +art_painting/horse/pic_143.jpg 5 +art_painting/horse/pic_147.jpg 5 +art_painting/horse/pic_144.jpg 5 +art_painting/horse/pic_146.jpg 5 +art_painting/horse/pic_155.jpg 5 +art_painting/horse/pic_142.jpg 5 +art_painting/horse/pic_136.jpg 5 +art_painting/horse/pic_148.jpg 5 +art_painting/horse/pic_162.jpg 5 +art_painting/horse/pic_163.jpg 5 +art_painting/horse/pic_128.jpg 5 +art_painting/horse/pic_154.jpg 5 +art_painting/horse/pic_150.jpg 5 +art_painting/horse/pic_151.jpg 5 +art_painting/horse/pic_152.jpg 5 +art_painting/horse/pic_182.jpg 5 +art_painting/horse/pic_157.jpg 5 +art_painting/horse/pic_130.jpg 5 +art_painting/horse/pic_180.jpg 5 +art_painting/horse/pic_158.jpg 5 +art_painting/horse/pic_204.jpg 5 +art_painting/horse/pic_195.jpg 5 +art_painting/horse/pic_188.jpg 5 +art_painting/horse/pic_159.jpg 5 +art_painting/horse/pic_170.jpg 5 +art_painting/horse/pic_168.jpg 5 +art_painting/horse/pic_165.jpg 5 +art_painting/horse/pic_164.jpg 5 +art_painting/horse/pic_161.jpg 5 +art_painting/house/pic_032.jpg 6 +art_painting/house/pic_019.jpg 6 +art_painting/house/pic_016.jpg 6 +art_painting/house/pic_034.jpg 6 +art_painting/house/pic_022.jpg 6 +art_painting/house/pic_023.jpg 6 +art_painting/house/pic_014.jpg 6 +art_painting/house/pic_025.jpg 6 +art_painting/house/pic_024.jpg 6 +art_painting/house/pic_037.jpg 6 +art_painting/house/pic_018.jpg 6 +art_painting/house/pic_031.jpg 6 +art_painting/house/pic_027.jpg 6 +art_painting/house/pic_029.jpg 6 +art_painting/house/pic_274.jpg 6 +art_painting/house/pic_162.jpg 6 +art_painting/house/pic_160.jpg 6 +art_painting/house/pic_272.jpg 6 +art_painting/house/pic_159.jpg 6 +art_painting/house/pic_161.jpg 6 +art_painting/house/pic_276.jpg 6 +art_painting/house/pic_295.jpg 6 +art_painting/house/pic_165.jpg 6 +art_painting/house/pic_294.jpg 6 +art_painting/house/pic_293.jpg 6 +art_painting/house/pic_163.jpg 6 +art_painting/house/pic_282.jpg 6 +art_painting/house/pic_166.jpg 6 +art_painting/house/pic_164.jpg 6 +art_painting/house/pic_281.jpg 6 +art_painting/house/pic_171.jpg 6 +art_painting/house/pic_311.jpg 6 +art_painting/house/pic_237.jpg 6 +art_painting/house/pic_235.jpg 6 +art_painting/house/pic_234.jpg 6 +art_painting/house/pic_232.jpg 6 +art_painting/house/pic_240.jpg 6 +art_painting/house/pic_251.jpg 6 +art_painting/house/pic_248.jpg 6 +art_painting/house/pic_247.jpg 6 +art_painting/house/pic_246.jpg 6 +art_painting/house/pic_245.jpg 6 +art_painting/house/pic_243.jpg 6 +art_painting/house/pic_242.jpg 6 +art_painting/house/pic_250.jpg 6 +art_painting/house/pic_270.jpg 6 +art_painting/house/pic_269.jpg 6 +art_painting/house/pic_264.jpg 6 +art_painting/house/pic_329.jpg 6 +art_painting/house/pic_297.jpg 6 +art_painting/house/pic_304.jpg 6 +art_painting/house/pic_303.jpg 6 +art_painting/house/pic_302.jpg 6 +art_painting/house/pic_319.jpg 6 +art_painting/house/pic_318.jpg 6 +art_painting/house/pic_317.jpg 6 +art_painting/house/pic_315.jpg 6 +art_painting/house/pic_309.jpg 6 +art_painting/house/pic_306.jpg 6 +art_painting/house/pic_305.jpg 6 +art_painting/house/pic_323.jpg 6 +art_painting/house/pic_324.jpg 6 +art_painting/house/pic_336.jpg 6 +art_painting/house/pic_330.jpg 6 +art_painting/house/pic_327.jpg 6 +art_painting/house/pic_129.jpg 6 +art_painting/house/pic_130.jpg 6 +art_painting/house/pic_131.jpg 6 +art_painting/house/pic_255.jpg 6 +art_painting/house/pic_253.jpg 6 +art_painting/house/pic_133.jpg 6 +art_painting/house/pic_132.jpg 6 +art_painting/house/pic_256.jpg 6 +art_painting/house/pic_134.jpg 6 +art_painting/house/pic_257.jpg 6 +art_painting/house/pic_137.jpg 6 +art_painting/house/pic_258.jpg 6 +art_painting/house/pic_136.jpg 6 +art_painting/house/pic_140.jpg 6 +art_painting/house/pic_142.jpg 6 +art_painting/house/pic_259.jpg 6 +art_painting/house/pic_141.jpg 6 +art_painting/house/pic_146.jpg 6 +art_painting/house/pic_147.jpg 6 +art_painting/house/pic_145.jpg 6 +art_painting/house/pic_254.jpg 6 +art_painting/house/pic_263.jpg 6 +art_painting/house/pic_278.jpg 6 +art_painting/house/pic_277.jpg 6 +art_painting/house/pic_279.jpg 6 +art_painting/house/pic_280.jpg 6 +art_painting/house/pic_283.jpg 6 +art_painting/house/pic_284.jpg 6 +art_painting/house/pic_285.jpg 6 +art_painting/house/pic_287.jpg 6 +art_painting/house/pic_296.jpg 6 +art_painting/house/pic_292.jpg 6 +art_painting/house/pic_289.jpg 6 +art_painting/house/pic_290.jpg 6 +art_painting/house/pic_291.jpg 6 +art_painting/house/pic_301.jpg 6 +art_painting/house/pic_299.jpg 6 +art_painting/house/pic_298.jpg 6 +art_painting/house/pic_189.jpg 6 +art_painting/house/pic_187.jpg 6 +art_painting/house/pic_194.jpg 6 +art_painting/house/pic_206.jpg 6 +art_painting/house/pic_205.jpg 6 +art_painting/house/pic_201.jpg 6 +art_painting/house/pic_200.jpg 6 +art_painting/house/pic_198.jpg 6 +art_painting/house/pic_196.jpg 6 +art_painting/house/pic_197.jpg 6 +art_painting/house/pic_195.jpg 6 +art_painting/house/pic_199.jpg 6 +art_painting/house/pic_203.jpg 6 +art_painting/house/pic_221.jpg 6 +art_painting/house/pic_219.jpg 6 +art_painting/house/pic_217.jpg 6 +art_painting/house/pic_216.jpg 6 +art_painting/house/pic_184.jpg 6 +art_painting/house/pic_181.jpg 6 +art_painting/house/pic_180.jpg 6 +art_painting/house/pic_182.jpg 6 +art_painting/house/pic_335.jpg 6 +art_painting/house/pic_340.jpg 6 +art_painting/house/pic_348.jpg 6 +art_painting/house/pic_185.jpg 6 +art_painting/house/pic_346.jpg 6 +art_painting/house/pic_345.jpg 6 +art_painting/house/pic_344.jpg 6 +art_painting/house/pic_343.jpg 6 +art_painting/house/pic_193.jpg 6 +art_painting/house/pic_192.jpg 6 +art_painting/house/pic_191.jpg 6 +art_painting/house/pic_074.jpg 6 +art_painting/house/pic_076.jpg 6 +art_painting/house/pic_075.jpg 6 +art_painting/house/pic_077.jpg 6 +art_painting/house/pic_087.jpg 6 +art_painting/house/pic_085.jpg 6 +art_painting/house/pic_084.jpg 6 +art_painting/house/pic_083.jpg 6 +art_painting/house/pic_080.jpg 6 +art_painting/house/pic_079.jpg 6 +art_painting/house/pic_078.jpg 6 +art_painting/house/pic_088.jpg 6 +art_painting/house/pic_082.jpg 6 +art_painting/house/pic_086.jpg 6 +art_painting/house/pic_123.jpg 6 +art_painting/house/pic_122.jpg 6 +art_painting/house/pic_119.jpg 6 +art_painting/house/pic_111.jpg 6 +art_painting/house/pic_108.jpg 6 +art_painting/house/pic_104.jpg 6 +art_painting/house/pic_215.jpg 6 +art_painting/house/pic_211.jpg 6 +art_painting/house/pic_209.jpg 6 +art_painting/house/pic_208.jpg 6 +art_painting/house/pic_207.jpg 6 +art_painting/house/pic_218.jpg 6 +art_painting/house/pic_210.jpg 6 +art_painting/house/pic_228.jpg 6 +art_painting/house/pic_227.jpg 6 +art_painting/house/pic_225.jpg 6 +art_painting/house/pic_224.jpg 6 +art_painting/house/pic_223.jpg 6 +art_painting/house/pic_222.jpg 6 +art_painting/house/pic_226.jpg 6 +art_painting/house/pic_230.jpg 6 +art_painting/house/pic_229.jpg 6 +art_painting/house/pic_231.jpg 6 +art_painting/house/pic_241.jpg 6 +art_painting/house/pic_144.jpg 6 +art_painting/house/pic_143.jpg 6 +art_painting/house/pic_149.jpg 6 +art_painting/house/pic_150.jpg 6 +art_painting/house/pic_151.jpg 6 +art_painting/house/pic_148.jpg 6 +art_painting/house/pic_260.jpg 6 +art_painting/house/pic_153.jpg 6 +art_painting/house/pic_152.jpg 6 +art_painting/house/pic_261.jpg 6 +art_painting/house/pic_262.jpg 6 +art_painting/house/pic_268.jpg 6 +art_painting/house/pic_156.jpg 6 +art_painting/house/pic_158.jpg 6 +art_painting/house/pic_157.jpg 6 +art_painting/house/pic_266.jpg 6 +art_painting/house/pic_267.jpg 6 +art_painting/house/pic_273.jpg 6 +art_painting/house/pic_097.jpg 6 +art_painting/house/pic_118.jpg 6 +art_painting/house/pic_114.jpg 6 +art_painting/house/pic_094.jpg 6 +art_painting/house/pic_101.jpg 6 +art_painting/house/pic_125.jpg 6 +art_painting/house/pic_113.jpg 6 +art_painting/house/pic_109.jpg 6 +art_painting/house/pic_098.jpg 6 +art_painting/house/pic_116.jpg 6 +art_painting/house/pic_127.jpg 6 +art_painting/house/pic_120.jpg 6 +art_painting/house/pic_138.jpg 6 +art_painting/house/pic_176.jpg 6 +art_painting/house/pic_177.jpg 6 +art_painting/house/pic_212.jpg 6 +art_painting/house/pic_213.jpg 6 +art_painting/house/pic_238.jpg 6 +art_painting/house/pic_128.jpg 6 +art_painting/house/pic_053.jpg 6 +art_painting/house/pic_055.jpg 6 +art_painting/house/pic_054.jpg 6 +art_painting/house/pic_057.jpg 6 +art_painting/house/pic_056.jpg 6 +art_painting/house/pic_058.jpg 6 +art_painting/house/pic_059.jpg 6 +art_painting/house/pic_061.jpg 6 +art_painting/house/pic_060.jpg 6 +art_painting/house/pic_062.jpg 6 +art_painting/house/pic_063.jpg 6 +art_painting/house/pic_067.jpg 6 +art_painting/house/pic_069.jpg 6 +art_painting/house/pic_068.jpg 6 +art_painting/house/pic_066.jpg 6 +art_painting/house/pic_071.jpg 6 +art_painting/house/pic_070.jpg 6 +art_painting/house/pic_072.jpg 6 +art_painting/house/pic_106.jpg 6 +art_painting/house/pic_107.jpg 6 +art_painting/house/pic_099.jpg 6 +art_painting/house/pic_100.jpg 6 +art_painting/house/pic_035.jpg 6 +art_painting/house/pic_095.jpg 6 +art_painting/house/pic_093.jpg 6 +art_painting/house/pic_090.jpg 6 +art_painting/house/pic_092.jpg 6 +art_painting/house/pic_091.jpg 6 +art_painting/house/pic_103.jpg 6 +art_painting/house/pic_124.jpg 6 +art_painting/house/pic_110.jpg 6 +art_painting/house/pic_117.jpg 6 +art_painting/house/pic_105.jpg 6 +art_painting/house/pic_121.jpg 6 +art_painting/house/pic_115.jpg 6 +art_painting/house/pic_028.jpg 6 +art_painting/house/pic_017.jpg 6 +art_painting/house/pic_038.jpg 6 +art_painting/house/pic_048.jpg 6 +art_painting/house/pic_047.jpg 6 +art_painting/house/pic_036.jpg 6 +art_painting/house/pic_043.jpg 6 +art_painting/house/pic_041.jpg 6 +art_painting/house/pic_040.jpg 6 +art_painting/house/pic_039.jpg 6 +art_painting/house/pic_021.jpg 6 +art_painting/house/pic_020.jpg 6 +art_painting/house/pic_026.jpg 6 +art_painting/house/pic_046.jpg 6 +art_painting/house/pic_044.jpg 6 +art_painting/house/pic_045.jpg 6 +art_painting/house/pic_042.jpg 6 +art_painting/house/pic_049.jpg 6 +art_painting/house/pic_050.jpg 6 +art_painting/house/pic_051.jpg 6 +art_painting/person/pic_436.jpg 7 +art_painting/person/pic_437.jpg 7 +art_painting/person/pic_438.jpg 7 +art_painting/person/pic_184.jpg 7 +art_painting/person/pic_186.jpg 7 +art_painting/person/pic_388.jpg 7 +art_painting/person/pic_410.jpg 7 +art_painting/person/pic_400.jpg 7 +art_painting/person/pic_391.jpg 7 +art_painting/person/pic_406.jpg 7 +art_painting/person/pic_407.jpg 7 +art_painting/person/pic_417.jpg 7 +art_painting/person/pic_435.jpg 7 +art_painting/person/pic_433.jpg 7 +art_painting/person/pic_431.jpg 7 +art_painting/person/pic_467.jpg 7 +art_painting/person/pic_247.jpg 7 +art_painting/person/pic_249.jpg 7 +art_painting/person/pic_252.jpg 7 +art_painting/person/pic_255.jpg 7 +art_painting/person/pic_531.jpg 7 +art_painting/person/pic_530.jpg 7 +art_painting/person/pic_264.jpg 7 +art_painting/person/pic_262.jpg 7 +art_painting/person/pic_549.jpg 7 +art_painting/person/pic_260.jpg 7 +art_painting/person/pic_548.jpg 7 +art_painting/person/pic_501.jpg 7 +art_painting/person/pic_495.jpg 7 +art_painting/person/pic_494.jpg 7 +art_painting/person/pic_506.jpg 7 +art_painting/person/pic_532.jpg 7 +art_painting/person/pic_527.jpg 7 +art_painting/person/pic_525.jpg 7 +art_painting/person/pic_519.jpg 7 +art_painting/person/pic_523.jpg 7 +art_painting/person/pic_521.jpg 7 +art_painting/person/pic_520.jpg 7 +art_painting/person/pic_512.jpg 7 +art_painting/person/pic_528.jpg 7 +art_painting/person/pic_526.jpg 7 +art_painting/person/pic_518.jpg 7 +art_painting/person/pic_534.jpg 7 +art_painting/person/pic_538.jpg 7 +art_painting/person/pic_026.jpg 7 +art_painting/person/pic_047.jpg 7 +art_painting/person/pic_030.jpg 7 +art_painting/person/pic_022.jpg 7 +art_painting/person/pic_032.jpg 7 +art_painting/person/pic_024.jpg 7 +art_painting/person/pic_044.jpg 7 +art_painting/person/pic_038.jpg 7 +art_painting/person/pic_027.jpg 7 +art_painting/person/pic_019.jpg 7 +art_painting/person/pic_034.jpg 7 +art_painting/person/pic_045.jpg 7 +art_painting/person/pic_023.jpg 7 +art_painting/person/pic_029.jpg 7 +art_painting/person/pic_025.jpg 7 +art_painting/person/pic_041.jpg 7 +art_painting/person/pic_039.jpg 7 +art_painting/person/pic_031.jpg 7 +art_painting/person/pic_046.jpg 7 +art_painting/person/pic_020.jpg 7 +art_painting/person/pic_040.jpg 7 +art_painting/person/pic_226.jpg 7 +art_painting/person/pic_229.jpg 7 +art_painting/person/pic_228.jpg 7 +art_painting/person/pic_484.jpg 7 +art_painting/person/pic_234.jpg 7 +art_painting/person/pic_231.jpg 7 +art_painting/person/pic_232.jpg 7 +art_painting/person/pic_235.jpg 7 +art_painting/person/pic_505.jpg 7 +art_painting/person/pic_243.jpg 7 +art_painting/person/pic_237.jpg 7 +art_painting/person/pic_456.jpg 7 +art_painting/person/pic_200.jpg 7 +art_painting/person/pic_459.jpg 7 +art_painting/person/pic_460.jpg 7 +art_painting/person/pic_203.jpg 7 +art_painting/person/pic_206.jpg 7 +art_painting/person/pic_204.jpg 7 +art_painting/person/pic_202.jpg 7 +art_painting/person/pic_201.jpg 7 +art_painting/person/pic_462.jpg 7 +art_painting/person/pic_205.jpg 7 +art_painting/person/pic_213.jpg 7 +art_painting/person/pic_470.jpg 7 +art_painting/person/pic_469.jpg 7 +art_painting/person/pic_464.jpg 7 +art_painting/person/pic_209.jpg 7 +art_painting/person/pic_208.jpg 7 +art_painting/person/pic_210.jpg 7 +art_painting/person/pic_497.jpg 7 +art_painting/person/pic_236.jpg 7 +art_painting/person/pic_496.jpg 7 +art_painting/person/pic_503.jpg 7 +art_painting/person/pic_238.jpg 7 +art_painting/person/pic_508.jpg 7 +art_painting/person/pic_507.jpg 7 +art_painting/person/pic_504.jpg 7 +art_painting/person/pic_245.jpg 7 +art_painting/person/pic_254.jpg 7 +art_painting/person/pic_253.jpg 7 +art_painting/person/pic_522.jpg 7 +art_painting/person/pic_248.jpg 7 +art_painting/person/pic_514.jpg 7 +art_painting/person/pic_513.jpg 7 +art_painting/person/pic_246.jpg 7 +art_painting/person/pic_250.jpg 7 +art_painting/person/pic_132.jpg 7 +art_painting/person/pic_116.jpg 7 +art_painting/person/pic_104.jpg 7 +art_painting/person/pic_112.jpg 7 +art_painting/person/pic_100.jpg 7 +art_painting/person/pic_117.jpg 7 +art_painting/person/pic_122.jpg 7 +art_painting/person/pic_121.jpg 7 +art_painting/person/pic_129.jpg 7 +art_painting/person/pic_136.jpg 7 +art_painting/person/pic_193.jpg 7 +art_painting/person/pic_194.jpg 7 +art_painting/person/pic_192.jpg 7 +art_painting/person/pic_195.jpg 7 +art_painting/person/pic_241.jpg 7 +art_painting/person/pic_242.jpg 7 +art_painting/person/pic_240.jpg 7 +art_painting/person/pic_152.jpg 7 +art_painting/person/pic_170.jpg 7 +art_painting/person/pic_171.jpg 7 +art_painting/person/pic_168.jpg 7 +art_painting/person/pic_167.jpg 7 +art_painting/person/pic_320.jpg 7 +art_painting/person/pic_319.jpg 7 +art_painting/person/pic_318.jpg 7 +art_painting/person/pic_164.jpg 7 +art_painting/person/pic_163.jpg 7 +art_painting/person/pic_162.jpg 7 +art_painting/person/pic_161.jpg 7 +art_painting/person/pic_316.jpg 7 +art_painting/person/pic_160.jpg 7 +art_painting/person/pic_321.jpg 7 +art_painting/person/pic_165.jpg 7 +art_painting/person/pic_317.jpg 7 +art_painting/person/pic_166.jpg 7 +art_painting/person/pic_169.jpg 7 +art_painting/person/pic_535.jpg 7 +art_painting/person/pic_543.jpg 7 +art_painting/person/pic_540.jpg 7 +art_painting/person/pic_539.jpg 7 +art_painting/person/pic_542.jpg 7 +art_painting/person/pic_545.jpg 7 +art_painting/person/pic_559.jpg 7 +art_painting/person/pic_555.jpg 7 +art_painting/person/pic_553.jpg 7 +art_painting/person/pic_551.jpg 7 +art_painting/person/pic_552.jpg 7 +art_painting/person/pic_550.jpg 7 +art_painting/person/pic_546.jpg 7 +art_painting/person/pic_556.jpg 7 +art_painting/person/pic_558.jpg 7 +art_painting/person/pic_572.jpg 7 +art_painting/person/pic_571.jpg 7 +art_painting/person/pic_570.jpg 7 +art_painting/person/pic_564.jpg 7 +art_painting/person/pic_563.jpg 7 +art_painting/person/pic_560.jpg 7 +art_painting/person/pic_561.jpg 7 +art_painting/person/pic_577.jpg 7 +art_painting/person/pic_259.jpg 7 +art_painting/person/pic_547.jpg 7 +art_painting/person/pic_257.jpg 7 +art_painting/person/pic_256.jpg 7 +art_painting/person/pic_537.jpg 7 +art_painting/person/pic_536.jpg 7 +art_painting/person/pic_263.jpg 7 +art_painting/person/pic_051.jpg 7 +art_painting/person/pic_268.jpg 7 +art_painting/person/pic_574.jpg 7 +art_painting/person/pic_573.jpg 7 +art_painting/person/pic_267.jpg 7 +art_painting/person/pic_266.jpg 7 +art_painting/person/pic_265.jpg 7 +art_painting/person/pic_272.jpg 7 +art_painting/person/pic_568.jpg 7 +art_painting/person/pic_569.jpg 7 +art_painting/person/pic_271.jpg 7 +art_painting/person/pic_113.jpg 7 +art_painting/person/pic_111.jpg 7 +art_painting/person/pic_109.jpg 7 +art_painting/person/pic_107.jpg 7 +art_painting/person/pic_106.jpg 7 +art_painting/person/pic_105.jpg 7 +art_painting/person/pic_101.jpg 7 +art_painting/person/pic_099.jpg 7 +art_painting/person/pic_131.jpg 7 +art_painting/person/pic_120.jpg 7 +art_painting/person/pic_110.jpg 7 +art_painting/person/pic_123.jpg 7 +art_painting/person/pic_108.jpg 7 +art_painting/person/pic_098.jpg 7 +art_painting/person/pic_364.jpg 7 +art_painting/person/pic_363.jpg 7 +art_painting/person/pic_356.jpg 7 +art_painting/person/pic_357.jpg 7 +art_painting/person/pic_366.jpg 7 +art_painting/person/pic_372.jpg 7 +art_painting/person/pic_377.jpg 7 +art_painting/person/pic_378.jpg 7 +art_painting/person/pic_376.jpg 7 +art_painting/person/pic_371.jpg 7 +art_painting/person/pic_375.jpg 7 +art_painting/person/pic_389.jpg 7 +art_painting/person/pic_387.jpg 7 +art_painting/person/pic_386.jpg 7 +art_painting/person/pic_385.jpg 7 +art_painting/person/pic_379.jpg 7 +art_painting/person/pic_214.jpg 7 +art_painting/person/pic_211.jpg 7 +art_painting/person/pic_471.jpg 7 +art_painting/person/pic_475.jpg 7 +art_painting/person/pic_220.jpg 7 +art_painting/person/pic_218.jpg 7 +art_painting/person/pic_216.jpg 7 +art_painting/person/pic_215.jpg 7 +art_painting/person/pic_221.jpg 7 +art_painting/person/pic_217.jpg 7 +art_painting/person/pic_219.jpg 7 +art_painting/person/pic_227.jpg 7 +art_painting/person/pic_480.jpg 7 +art_painting/person/pic_479.jpg 7 +art_painting/person/pic_476.jpg 7 +art_painting/person/pic_224.jpg 7 +art_painting/person/pic_223.jpg 7 +art_painting/person/pic_222.jpg 7 +art_painting/person/pic_322.jpg 7 +art_painting/person/pic_306.jpg 7 +art_painting/person/pic_333.jpg 7 +art_painting/person/pic_346.jpg 7 +art_painting/person/pic_354.jpg 7 +art_painting/person/pic_353.jpg 7 +art_painting/person/pic_352.jpg 7 +art_painting/person/pic_351.jpg 7 +art_painting/person/pic_349.jpg 7 +art_painting/person/pic_347.jpg 7 +art_painting/person/pic_345.jpg 7 +art_painting/person/pic_338.jpg 7 +art_painting/person/pic_337.jpg 7 +art_painting/person/pic_350.jpg 7 +art_painting/person/pic_339.jpg 7 +art_painting/person/pic_368.jpg 7 +art_painting/person/pic_308.jpg 7 +art_painting/person/pic_151.jpg 7 +art_painting/person/pic_150.jpg 7 +art_painting/person/pic_149.jpg 7 +art_painting/person/pic_313.jpg 7 +art_painting/person/pic_148.jpg 7 +art_painting/person/pic_146.jpg 7 +art_painting/person/pic_311.jpg 7 +art_painting/person/pic_143.jpg 7 +art_painting/person/pic_144.jpg 7 +art_painting/person/pic_147.jpg 7 +art_painting/person/pic_145.jpg 7 +art_painting/person/pic_312.jpg 7 +art_painting/person/pic_314.jpg 7 +art_painting/person/pic_158.jpg 7 +art_painting/person/pic_157.jpg 7 +art_painting/person/pic_156.jpg 7 +art_painting/person/pic_155.jpg 7 +art_painting/person/pic_290.jpg 7 +art_painting/person/pic_288.jpg 7 +art_painting/person/pic_287.jpg 7 +art_painting/person/pic_294.jpg 7 +art_painting/person/pic_293.jpg 7 +art_painting/person/pic_292.jpg 7 +art_painting/person/pic_291.jpg 7 +art_painting/person/pic_301.jpg 7 +art_painting/person/pic_300.jpg 7 +art_painting/person/pic_305.jpg 7 +art_painting/person/pic_303.jpg 7 +art_painting/person/pic_304.jpg 7 +art_painting/person/pic_336.jpg 7 +art_painting/person/pic_325.jpg 7 +art_painting/person/pic_324.jpg 7 +art_painting/person/pic_006.jpg 7 +art_painting/person/pic_007.jpg 7 +art_painting/person/pic_008.jpg 7 +art_painting/person/pic_009.jpg 7 +art_painting/person/pic_010.jpg 7 +art_painting/person/pic_011.jpg 7 +art_painting/person/pic_012.jpg 7 +art_painting/person/pic_013.jpg 7 +art_painting/person/pic_014.jpg 7 +art_painting/person/pic_015.jpg 7 +art_painting/person/pic_016.jpg 7 +art_painting/person/pic_042.jpg 7 +art_painting/person/pic_033.jpg 7 +art_painting/person/pic_018.jpg 7 +art_painting/person/pic_036.jpg 7 +art_painting/person/pic_017.jpg 7 +art_painting/person/pic_037.jpg 7 +art_painting/person/pic_028.jpg 7 +art_painting/person/pic_043.jpg 7 +art_painting/person/pic_035.jpg 7 +art_painting/person/pic_327.jpg 7 +art_painting/person/pic_175.jpg 7 +art_painting/person/pic_328.jpg 7 +art_painting/person/pic_326.jpg 7 +art_painting/person/pic_174.jpg 7 +art_painting/person/pic_172.jpg 7 +art_painting/person/pic_329.jpg 7 +art_painting/person/pic_173.jpg 7 +art_painting/person/pic_178.jpg 7 +art_painting/person/pic_334.jpg 7 +art_painting/person/pic_335.jpg 7 +art_painting/person/pic_342.jpg 7 +art_painting/person/pic_181.jpg 7 +art_painting/person/pic_343.jpg 7 +art_painting/person/pic_180.jpg 7 +art_painting/person/pic_340.jpg 7 +art_painting/person/pic_359.jpg 7 +art_painting/person/pic_064.jpg 7 +art_painting/person/pic_062.jpg 7 +art_painting/person/pic_059.jpg 7 +art_painting/person/pic_060.jpg 7 +art_painting/person/pic_066.jpg 7 +art_painting/person/pic_063.jpg 7 +art_painting/person/pic_071.jpg 7 +art_painting/person/pic_070.jpg 7 +art_painting/person/pic_069.jpg 7 +art_painting/person/pic_072.jpg 7 +art_painting/person/pic_076.jpg 7 +art_painting/person/pic_074.jpg 7 +art_painting/person/pic_077.jpg 7 +art_painting/person/pic_078.jpg 7 +art_painting/person/pic_079.jpg 7 +art_painting/person/pic_080.jpg 7 +art_painting/person/pic_081.jpg 7 +art_painting/person/pic_082.jpg 7 +art_painting/person/pic_083.jpg 7 +art_painting/person/pic_094.jpg 7 +art_painting/person/pic_093.jpg 7 +art_painting/person/pic_089.jpg 7 +art_painting/person/pic_090.jpg 7 +art_painting/person/pic_086.jpg 7 +art_painting/person/pic_097.jpg 7 +art_painting/person/pic_124.jpg 7 +art_painting/person/pic_128.jpg 7 +art_painting/person/pic_127.jpg 7 +art_painting/person/pic_126.jpg 7 +art_painting/person/pic_115.jpg 7 +art_painting/person/pic_114.jpg 7 +art_painting/person/pic_463.jpg 7 +art_painting/person/pic_458.jpg 7 +art_painting/person/pic_444.jpg 7 +art_painting/person/pic_445.jpg 7 +art_painting/person/pic_466.jpg 7 +art_painting/person/pic_465.jpg 7 +art_painting/person/pic_493.jpg 7 +art_painting/person/pic_490.jpg 7 +art_painting/person/pic_487.jpg 7 +art_painting/person/pic_481.jpg 7 +art_painting/person/pic_474.jpg 7 +art_painting/person/pic_468.jpg 7 +art_painting/person/pic_492.jpg 7 +art_painting/person/pic_473.jpg 7 +art_painting/person/pic_511.jpg 7 +art_painting/person/pic_510.jpg 7 +art_painting/person/pic_502.jpg 7 +art_painting/person/pic_187.jpg 7 +art_painting/person/pic_441.jpg 7 +art_painting/person/pic_440.jpg 7 +art_painting/person/pic_188.jpg 7 +art_painting/person/pic_450.jpg 7 +art_painting/person/pic_449.jpg 7 +art_painting/person/pic_448.jpg 7 +art_painting/person/pic_447.jpg 7 +art_painting/person/pic_190.jpg 7 +art_painting/person/pic_454.jpg 7 +art_painting/person/pic_455.jpg 7 +art_painting/person/pic_199.jpg 7 +art_painting/person/pic_197.jpg 7 +art_painting/person/pic_198.jpg 7 +art_painting/person/pic_196.jpg 7 +art_painting/person/pic_191.jpg 7 +art_painting/person/pic_358.jpg 7 +art_painting/person/pic_361.jpg 7 +art_painting/person/pic_362.jpg 7 +art_painting/person/pic_382.jpg 7 +art_painting/person/pic_380.jpg 7 +art_painting/person/pic_381.jpg 7 +art_painting/person/pic_383.jpg 7 +art_painting/person/pic_398.jpg 7 +art_painting/person/pic_395.jpg 7 +art_painting/person/pic_394.jpg 7 +art_painting/person/pic_396.jpg 7 +art_painting/person/pic_397.jpg 7 +art_painting/person/pic_402.jpg 7 +art_painting/person/pic_404.jpg 7 +art_painting/person/pic_405.jpg 7 +art_painting/person/pic_412.jpg 7 +art_painting/person/pic_414.jpg 7 +art_painting/person/pic_413.jpg 7 diff --git a/domainlab/zdata/pacs_split/cartoon_10.txt b/domainlab/zdata/pacs_split/cartoon_10.txt new file mode 100644 index 000000000..9c90dce46 --- /dev/null +++ b/domainlab/zdata/pacs_split/cartoon_10.txt @@ -0,0 +1,10 @@ +cartoon/person/pic_180.jpg 7 +cartoon/dog/pic_112.jpg 1 +cartoon/giraffe/pic_377.jpg 3 +cartoon/person/pic_111.jpg 7 +cartoon/giraffe/pic_382.jpg 3 +cartoon/horse/pic_064.jpg 5 +cartoon/dog/pic_137.jpg 1 +cartoon/house/pic_040.jpg 6 +cartoon/dog/pic_219.jpg 1 +cartoon/elephant/pic_332.jpg 2 diff --git a/domainlab/zdata/pacs_split/cartoon_100.txt b/domainlab/zdata/pacs_split/cartoon_100.txt new file mode 100644 index 000000000..678652e4c --- /dev/null +++ b/domainlab/zdata/pacs_split/cartoon_100.txt @@ -0,0 +1,100 @@ +cartoon/house/pic_032.jpg 6 +cartoon/giraffe/pic_286.jpg 3 +cartoon/giraffe/pic_147.jpg 3 +cartoon/horse/pic_303.jpg 5 +cartoon/giraffe/pic_193.jpg 3 +cartoon/elephant/pic_496.jpg 2 +cartoon/giraffe/pic_275.jpg 3 +cartoon/dog/pic_423.jpg 1 +cartoon/person/pic_340.jpg 7 +cartoon/dog/pic_332.jpg 1 +cartoon/elephant/pic_328.jpg 2 +cartoon/horse/pic_276.jpg 5 +cartoon/guitar/pic_081.jpg 4 +cartoon/person/pic_045.jpg 7 +cartoon/dog/pic_279.jpg 1 +cartoon/elephant/pic_065.jpg 2 +cartoon/guitar/pic_026.jpg 4 +cartoon/house/pic_176.jpg 6 +cartoon/guitar/pic_103.jpg 4 +cartoon/horse/pic_300.jpg 5 +cartoon/dog/pic_363.jpg 1 +cartoon/dog/pic_213.jpg 1 +cartoon/person/pic_276.jpg 7 +cartoon/dog/pic_195.jpg 1 +cartoon/giraffe/pic_262.jpg 3 +cartoon/person/pic_380.jpg 7 +cartoon/elephant/pic_179.jpg 2 +cartoon/person/pic_399.jpg 7 +cartoon/horse/pic_057.jpg 5 +cartoon/giraffe/pic_071.jpg 3 +cartoon/horse/pic_103.jpg 5 +cartoon/elephant/pic_101.jpg 2 +cartoon/elephant/pic_294.jpg 2 +cartoon/house/pic_188.jpg 6 +cartoon/giraffe/pic_361.jpg 3 +cartoon/giraffe/pic_139.jpg 3 +cartoon/horse/pic_056.jpg 5 +cartoon/elephant/pic_427.jpg 2 +cartoon/giraffe/pic_051.jpg 3 +cartoon/horse/pic_258.jpg 5 +cartoon/giraffe/pic_241.jpg 3 +cartoon/dog/pic_244.jpg 1 +cartoon/person/pic_303.jpg 7 +cartoon/giraffe/pic_368.jpg 3 +cartoon/house/pic_065.jpg 6 +cartoon/person/pic_080.jpg 7 +cartoon/person/pic_410.jpg 7 +cartoon/house/pic_264.jpg 6 +cartoon/elephant/pic_197.jpg 2 +cartoon/giraffe/pic_208.jpg 3 +cartoon/horse/pic_254.jpg 5 +cartoon/giraffe/pic_116.jpg 3 +cartoon/person/pic_229.jpg 7 +cartoon/elephant/pic_042.jpg 2 +cartoon/house/pic_147.jpg 6 +cartoon/dog/pic_102.jpg 1 +cartoon/horse/pic_160.jpg 5 +cartoon/elephant/pic_203.jpg 2 +cartoon/dog/pic_008.jpg 1 +cartoon/dog/pic_132.jpg 1 +cartoon/elephant/pic_059.jpg 2 +cartoon/elephant/pic_501.jpg 2 +cartoon/elephant/pic_254.jpg 2 +cartoon/giraffe/pic_200.jpg 3 +cartoon/elephant/pic_419.jpg 2 +cartoon/giraffe/pic_224.jpg 3 +cartoon/person/pic_146.jpg 7 +cartoon/giraffe/pic_129.jpg 3 +cartoon/giraffe/pic_370.jpg 3 +cartoon/guitar/pic_147.jpg 4 +cartoon/dog/pic_387.jpg 1 +cartoon/person/pic_390.jpg 7 +cartoon/horse/pic_356.jpg 5 +cartoon/guitar/pic_057.jpg 4 +cartoon/person/pic_219.jpg 7 +cartoon/elephant/pic_266.jpg 2 +cartoon/horse/pic_142.jpg 5 +cartoon/guitar/pic_037.jpg 4 +cartoon/dog/pic_112.jpg 1 +cartoon/house/pic_231.jpg 6 +cartoon/dog/pic_178.jpg 1 +cartoon/person/pic_033.jpg 7 +cartoon/dog/pic_007.jpg 1 +cartoon/dog/pic_062.jpg 1 +cartoon/house/pic_158.jpg 6 +cartoon/house/pic_301.jpg 6 +cartoon/horse/pic_137.jpg 5 +cartoon/dog/pic_338.jpg 1 +cartoon/giraffe/pic_165.jpg 3 +cartoon/elephant/pic_216.jpg 2 +cartoon/horse/pic_307.jpg 5 +cartoon/person/pic_026.jpg 7 +cartoon/person/pic_429.jpg 7 +cartoon/giraffe/pic_222.jpg 3 +cartoon/elephant/pic_461.jpg 2 +cartoon/horse/pic_298.jpg 5 +cartoon/person/pic_375.jpg 7 +cartoon/person/pic_373.jpg 7 +cartoon/house/pic_118.jpg 6 +cartoon/giraffe/pic_047.jpg 3 diff --git a/domainlab/zdata/pacs_split/cartoon_crossval_kfold.txt b/domainlab/zdata/pacs_split/cartoon_crossval_kfold.txt new file mode 100644 index 000000000..e8374913b --- /dev/null +++ b/domainlab/zdata/pacs_split/cartoon_crossval_kfold.txt @@ -0,0 +1,237 @@ +cartoon/dog/pic_383.jpg 1 +cartoon/dog/pic_382.jpg 1 +cartoon/dog/pic_386.jpg 1 +cartoon/dog/pic_384.jpg 1 +cartoon/dog/pic_385.jpg 1 +cartoon/dog/pic_391.jpg 1 +cartoon/dog/pic_390.jpg 1 +cartoon/dog/pic_392.jpg 1 +cartoon/dog/pic_393.jpg 1 +cartoon/dog/pic_405.jpg 1 +cartoon/dog/pic_403.jpg 1 +cartoon/dog/pic_417.jpg 1 +cartoon/dog/pic_416.jpg 1 +cartoon/dog/pic_415.jpg 1 +cartoon/dog/pic_150.jpg 1 +cartoon/dog/pic_233.jpg 1 +cartoon/dog/pic_232.jpg 1 +cartoon/dog/pic_227.jpg 1 +cartoon/dog/pic_228.jpg 1 +cartoon/dog/pic_229.jpg 1 +cartoon/dog/pic_226.jpg 1 +cartoon/dog/pic_230.jpg 1 +cartoon/dog/pic_286.jpg 1 +cartoon/dog/pic_285.jpg 1 +cartoon/dog/pic_276.jpg 1 +cartoon/dog/pic_262.jpg 1 +cartoon/dog/pic_259.jpg 1 +cartoon/dog/pic_257.jpg 1 +cartoon/dog/pic_254.jpg 1 +cartoon/dog/pic_252.jpg 1 +cartoon/dog/pic_249.jpg 1 +cartoon/dog/pic_001.jpg 1 +cartoon/dog/pic_003.jpg 1 +cartoon/dog/pic_004.jpg 1 +cartoon/dog/pic_005.jpg 1 +cartoon/dog/pic_006.jpg 1 +cartoon/dog/pic_031.jpg 1 +cartoon/dog/pic_043.jpg 1 +cartoon/dog/pic_025.jpg 1 +cartoon/elephant/pic_211.jpg 2 +cartoon/elephant/pic_154.jpg 2 +cartoon/elephant/pic_153.jpg 2 +cartoon/elephant/pic_237.jpg 2 +cartoon/elephant/pic_227.jpg 2 +cartoon/elephant/pic_226.jpg 2 +cartoon/elephant/pic_225.jpg 2 +cartoon/elephant/pic_155.jpg 2 +cartoon/elephant/pic_165.jpg 2 +cartoon/elephant/pic_164.jpg 2 +cartoon/elephant/pic_162.jpg 2 +cartoon/elephant/pic_157.jpg 2 +cartoon/elephant/pic_156.jpg 2 +cartoon/elephant/pic_166.jpg 2 +cartoon/elephant/pic_168.jpg 2 +cartoon/elephant/pic_167.jpg 2 +cartoon/elephant/pic_169.jpg 2 +cartoon/elephant/pic_171.jpg 2 +cartoon/elephant/pic_170.jpg 2 +cartoon/elephant/pic_240.jpg 2 +cartoon/elephant/pic_243.jpg 2 +cartoon/elephant/pic_242.jpg 2 +cartoon/elephant/pic_244.jpg 2 +cartoon/elephant/pic_172.jpg 2 +cartoon/elephant/pic_247.jpg 2 +cartoon/elephant/pic_248.jpg 2 +cartoon/elephant/pic_251.jpg 2 +cartoon/elephant/pic_250.jpg 2 +cartoon/elephant/pic_249.jpg 2 +cartoon/elephant/pic_252.jpg 2 +cartoon/elephant/pic_258.jpg 2 +cartoon/elephant/pic_257.jpg 2 +cartoon/elephant/pic_173.jpg 2 +cartoon/elephant/pic_412.jpg 2 +cartoon/elephant/pic_411.jpg 2 +cartoon/elephant/pic_408.jpg 2 +cartoon/elephant/pic_409.jpg 2 +cartoon/elephant/pic_413.jpg 2 +cartoon/elephant/pic_410.jpg 2 +cartoon/elephant/pic_431.jpg 2 +cartoon/elephant/pic_430.jpg 2 +cartoon/elephant/pic_428.jpg 2 +cartoon/elephant/pic_425.jpg 2 +cartoon/elephant/pic_423.jpg 2 +cartoon/elephant/pic_424.jpg 2 +cartoon/elephant/pic_420.jpg 2 +cartoon/giraffe/pic_005.jpg 3 +cartoon/giraffe/pic_006.jpg 3 +cartoon/giraffe/pic_007.jpg 3 +cartoon/giraffe/pic_008.jpg 3 +cartoon/giraffe/pic_009.jpg 3 +cartoon/giraffe/pic_010.jpg 3 +cartoon/giraffe/pic_011.jpg 3 +cartoon/giraffe/pic_012.jpg 3 +cartoon/giraffe/pic_013.jpg 3 +cartoon/giraffe/pic_014.jpg 3 +cartoon/giraffe/pic_015.jpg 3 +cartoon/giraffe/pic_016.jpg 3 +cartoon/giraffe/pic_017.jpg 3 +cartoon/giraffe/pic_018.jpg 3 +cartoon/giraffe/pic_019.jpg 3 +cartoon/giraffe/pic_020.jpg 3 +cartoon/giraffe/pic_022.jpg 3 +cartoon/giraffe/pic_025.jpg 3 +cartoon/giraffe/pic_024.jpg 3 +cartoon/giraffe/pic_091.jpg 3 +cartoon/giraffe/pic_090.jpg 3 +cartoon/giraffe/pic_087.jpg 3 +cartoon/giraffe/pic_086.jpg 3 +cartoon/giraffe/pic_085.jpg 3 +cartoon/giraffe/pic_095.jpg 3 +cartoon/giraffe/pic_096.jpg 3 +cartoon/giraffe/pic_093.jpg 3 +cartoon/giraffe/pic_094.jpg 3 +cartoon/giraffe/pic_106.jpg 3 +cartoon/giraffe/pic_108.jpg 3 +cartoon/giraffe/pic_104.jpg 3 +cartoon/giraffe/pic_103.jpg 3 +cartoon/giraffe/pic_101.jpg 3 +cartoon/giraffe/pic_100.jpg 3 +cartoon/giraffe/pic_099.jpg 3 +cartoon/guitar/pic_072.jpg 4 +cartoon/guitar/pic_003.jpg 4 +cartoon/guitar/pic_004.jpg 4 +cartoon/guitar/pic_005.jpg 4 +cartoon/guitar/pic_006.jpg 4 +cartoon/guitar/pic_007.jpg 4 +cartoon/guitar/pic_009.jpg 4 +cartoon/guitar/pic_010.jpg 4 +cartoon/guitar/pic_011.jpg 4 +cartoon/guitar/pic_012.jpg 4 +cartoon/guitar/pic_013.jpg 4 +cartoon/guitar/pic_016.jpg 4 +cartoon/guitar/pic_017.jpg 4 +cartoon/guitar/pic_020.jpg 4 +cartoon/horse/pic_329.jpg 5 +cartoon/horse/pic_317.jpg 5 +cartoon/horse/pic_331.jpg 5 +cartoon/horse/pic_333.jpg 5 +cartoon/horse/pic_332.jpg 5 +cartoon/horse/pic_334.jpg 5 +cartoon/horse/pic_324.jpg 5 +cartoon/horse/pic_318.jpg 5 +cartoon/horse/pic_338.jpg 5 +cartoon/horse/pic_337.jpg 5 +cartoon/horse/pic_341.jpg 5 +cartoon/horse/pic_340.jpg 5 +cartoon/horse/pic_335.jpg 5 +cartoon/horse/pic_342.jpg 5 +cartoon/horse/pic_347.jpg 5 +cartoon/horse/pic_346.jpg 5 +cartoon/horse/pic_343.jpg 5 +cartoon/horse/pic_336.jpg 5 +cartoon/horse/pic_348.jpg 5 +cartoon/horse/pic_339.jpg 5 +cartoon/horse/pic_349.jpg 5 +cartoon/horse/pic_139.jpg 5 +cartoon/horse/pic_132.jpg 5 +cartoon/horse/pic_141.jpg 5 +cartoon/horse/pic_133.jpg 5 +cartoon/horse/pic_162.jpg 5 +cartoon/horse/pic_155.jpg 5 +cartoon/horse/pic_159.jpg 5 +cartoon/horse/pic_156.jpg 5 +cartoon/horse/pic_151.jpg 5 +cartoon/horse/pic_149.jpg 5 +cartoon/horse/pic_147.jpg 5 +cartoon/horse/pic_161.jpg 5 +cartoon/house/pic_103.jpg 6 +cartoon/house/pic_091.jpg 6 +cartoon/house/pic_089.jpg 6 +cartoon/house/pic_092.jpg 6 +cartoon/house/pic_093.jpg 6 +cartoon/house/pic_107.jpg 6 +cartoon/house/pic_104.jpg 6 +cartoon/house/pic_114.jpg 6 +cartoon/house/pic_112.jpg 6 +cartoon/house/pic_109.jpg 6 +cartoon/house/pic_108.jpg 6 +cartoon/house/pic_102.jpg 6 +cartoon/house/pic_099.jpg 6 +cartoon/house/pic_098.jpg 6 +cartoon/house/pic_097.jpg 6 +cartoon/house/pic_111.jpg 6 +cartoon/house/pic_320.jpg 6 +cartoon/house/pic_321.jpg 6 +cartoon/house/pic_315.jpg 6 +cartoon/house/pic_322.jpg 6 +cartoon/house/pic_323.jpg 6 +cartoon/house/pic_311.jpg 6 +cartoon/house/pic_324.jpg 6 +cartoon/house/pic_327.jpg 6 +cartoon/house/pic_312.jpg 6 +cartoon/house/pic_314.jpg 6 +cartoon/house/pic_328.jpg 6 +cartoon/house/pic_069.jpg 6 +cartoon/house/pic_079.jpg 6 +cartoon/person/pic_308.jpg 7 +cartoon/person/pic_307.jpg 7 +cartoon/person/pic_306.jpg 7 +cartoon/person/pic_313.jpg 7 +cartoon/person/pic_323.jpg 7 +cartoon/person/pic_319.jpg 7 +cartoon/person/pic_320.jpg 7 +cartoon/person/pic_321.jpg 7 +cartoon/person/pic_318.jpg 7 +cartoon/person/pic_317.jpg 7 +cartoon/person/pic_316.jpg 7 +cartoon/person/pic_324.jpg 7 +cartoon/person/pic_334.jpg 7 +cartoon/person/pic_331.jpg 7 +cartoon/person/pic_332.jpg 7 +cartoon/person/pic_333.jpg 7 +cartoon/person/pic_144.jpg 7 +cartoon/person/pic_145.jpg 7 +cartoon/person/pic_143.jpg 7 +cartoon/person/pic_138.jpg 7 +cartoon/person/pic_154.jpg 7 +cartoon/person/pic_151.jpg 7 +cartoon/person/pic_152.jpg 7 +cartoon/person/pic_148.jpg 7 +cartoon/person/pic_149.jpg 7 +cartoon/person/pic_155.jpg 7 +cartoon/person/pic_157.jpg 7 +cartoon/person/pic_159.jpg 7 +cartoon/person/pic_176.jpg 7 +cartoon/person/pic_171.jpg 7 +cartoon/person/pic_168.jpg 7 +cartoon/person/pic_169.jpg 7 +cartoon/person/pic_167.jpg 7 +cartoon/person/pic_056.jpg 7 +cartoon/person/pic_071.jpg 7 +cartoon/person/pic_070.jpg 7 +cartoon/person/pic_069.jpg 7 +cartoon/person/pic_073.jpg 7 +cartoon/person/pic_075.jpg 7 +cartoon/person/pic_076.jpg 7 +cartoon/person/pic_068.jpg 7 diff --git a/domainlab/zdata/pacs_split/cartoon_test_kfold.txt b/domainlab/zdata/pacs_split/cartoon_test_kfold.txt new file mode 100644 index 000000000..5daf9281e --- /dev/null +++ b/domainlab/zdata/pacs_split/cartoon_test_kfold.txt @@ -0,0 +1,2344 @@ +cartoon/dog/pic_383.jpg 1 +cartoon/dog/pic_382.jpg 1 +cartoon/dog/pic_386.jpg 1 +cartoon/dog/pic_384.jpg 1 +cartoon/dog/pic_385.jpg 1 +cartoon/dog/pic_391.jpg 1 +cartoon/dog/pic_390.jpg 1 +cartoon/dog/pic_392.jpg 1 +cartoon/dog/pic_393.jpg 1 +cartoon/dog/pic_405.jpg 1 +cartoon/dog/pic_403.jpg 1 +cartoon/dog/pic_417.jpg 1 +cartoon/dog/pic_416.jpg 1 +cartoon/dog/pic_415.jpg 1 +cartoon/dog/pic_150.jpg 1 +cartoon/dog/pic_233.jpg 1 +cartoon/dog/pic_232.jpg 1 +cartoon/dog/pic_227.jpg 1 +cartoon/dog/pic_228.jpg 1 +cartoon/dog/pic_229.jpg 1 +cartoon/dog/pic_226.jpg 1 +cartoon/dog/pic_230.jpg 1 +cartoon/dog/pic_286.jpg 1 +cartoon/dog/pic_285.jpg 1 +cartoon/dog/pic_276.jpg 1 +cartoon/dog/pic_262.jpg 1 +cartoon/dog/pic_259.jpg 1 +cartoon/dog/pic_257.jpg 1 +cartoon/dog/pic_254.jpg 1 +cartoon/dog/pic_252.jpg 1 +cartoon/dog/pic_249.jpg 1 +cartoon/dog/pic_001.jpg 1 +cartoon/dog/pic_003.jpg 1 +cartoon/dog/pic_004.jpg 1 +cartoon/dog/pic_005.jpg 1 +cartoon/dog/pic_006.jpg 1 +cartoon/dog/pic_031.jpg 1 +cartoon/dog/pic_043.jpg 1 +cartoon/dog/pic_025.jpg 1 +cartoon/dog/pic_056.jpg 1 +cartoon/dog/pic_052.jpg 1 +cartoon/dog/pic_049.jpg 1 +cartoon/dog/pic_019.jpg 1 +cartoon/dog/pic_023.jpg 1 +cartoon/dog/pic_048.jpg 1 +cartoon/dog/pic_044.jpg 1 +cartoon/dog/pic_042.jpg 1 +cartoon/dog/pic_038.jpg 1 +cartoon/dog/pic_033.jpg 1 +cartoon/dog/pic_040.jpg 1 +cartoon/dog/pic_055.jpg 1 +cartoon/dog/pic_053.jpg 1 +cartoon/dog/pic_041.jpg 1 +cartoon/dog/pic_039.jpg 1 +cartoon/dog/pic_111.jpg 1 +cartoon/dog/pic_109.jpg 1 +cartoon/dog/pic_114.jpg 1 +cartoon/dog/pic_140.jpg 1 +cartoon/dog/pic_142.jpg 1 +cartoon/dog/pic_138.jpg 1 +cartoon/dog/pic_135.jpg 1 +cartoon/dog/pic_129.jpg 1 +cartoon/dog/pic_125.jpg 1 +cartoon/dog/pic_122.jpg 1 +cartoon/dog/pic_121.jpg 1 +cartoon/dog/pic_117.jpg 1 +cartoon/dog/pic_115.jpg 1 +cartoon/dog/pic_112.jpg 1 +cartoon/dog/pic_120.jpg 1 +cartoon/dog/pic_143.jpg 1 +cartoon/dog/pic_346.jpg 1 +cartoon/dog/pic_349.jpg 1 +cartoon/dog/pic_347.jpg 1 +cartoon/dog/pic_340.jpg 1 +cartoon/dog/pic_332.jpg 1 +cartoon/dog/pic_358.jpg 1 +cartoon/dog/pic_351.jpg 1 +cartoon/dog/pic_361.jpg 1 +cartoon/dog/pic_360.jpg 1 +cartoon/dog/pic_446.jpg 1 +cartoon/dog/pic_430.jpg 1 +cartoon/dog/pic_427.jpg 1 +cartoon/dog/pic_381.jpg 1 +cartoon/dog/pic_379.jpg 1 +cartoon/dog/pic_373.jpg 1 +cartoon/dog/pic_400.jpg 1 +cartoon/dog/pic_429.jpg 1 +cartoon/dog/pic_442.jpg 1 +cartoon/dog/pic_134.jpg 1 +cartoon/dog/pic_137.jpg 1 +cartoon/dog/pic_136.jpg 1 +cartoon/dog/pic_118.jpg 1 +cartoon/dog/pic_126.jpg 1 +cartoon/dog/pic_133.jpg 1 +cartoon/dog/pic_124.jpg 1 +cartoon/dog/pic_127.jpg 1 +cartoon/dog/pic_139.jpg 1 +cartoon/dog/pic_145.jpg 1 +cartoon/dog/pic_132.jpg 1 +cartoon/dog/pic_141.jpg 1 +cartoon/dog/pic_152.jpg 1 +cartoon/dog/pic_151.jpg 1 +cartoon/dog/pic_153.jpg 1 +cartoon/dog/pic_155.jpg 1 +cartoon/dog/pic_217.jpg 1 +cartoon/dog/pic_218.jpg 1 +cartoon/dog/pic_244.jpg 1 +cartoon/dog/pic_246.jpg 1 +cartoon/dog/pic_245.jpg 1 +cartoon/dog/pic_243.jpg 1 +cartoon/dog/pic_241.jpg 1 +cartoon/dog/pic_296.jpg 1 +cartoon/dog/pic_300.jpg 1 +cartoon/dog/pic_277.jpg 1 +cartoon/dog/pic_290.jpg 1 +cartoon/dog/pic_284.jpg 1 +cartoon/dog/pic_256.jpg 1 +cartoon/dog/pic_255.jpg 1 +cartoon/dog/pic_261.jpg 1 +cartoon/dog/pic_294.jpg 1 +cartoon/dog/pic_247.jpg 1 +cartoon/dog/pic_267.jpg 1 +cartoon/dog/pic_265.jpg 1 +cartoon/dog/pic_208.jpg 1 +cartoon/dog/pic_205.jpg 1 +cartoon/dog/pic_207.jpg 1 +cartoon/dog/pic_206.jpg 1 +cartoon/dog/pic_209.jpg 1 +cartoon/dog/pic_224.jpg 1 +cartoon/dog/pic_223.jpg 1 +cartoon/dog/pic_222.jpg 1 +cartoon/dog/pic_215.jpg 1 +cartoon/dog/pic_221.jpg 1 +cartoon/dog/pic_214.jpg 1 +cartoon/dog/pic_212.jpg 1 +cartoon/dog/pic_211.jpg 1 +cartoon/dog/pic_210.jpg 1 +cartoon/dog/pic_213.jpg 1 +cartoon/dog/pic_239.jpg 1 +cartoon/dog/pic_237.jpg 1 +cartoon/dog/pic_234.jpg 1 +cartoon/dog/pic_235.jpg 1 +cartoon/dog/pic_007.jpg 1 +cartoon/dog/pic_008.jpg 1 +cartoon/dog/pic_009.jpg 1 +cartoon/dog/pic_010.jpg 1 +cartoon/dog/pic_011.jpg 1 +cartoon/dog/pic_012.jpg 1 +cartoon/dog/pic_013.jpg 1 +cartoon/dog/pic_014.jpg 1 +cartoon/dog/pic_015.jpg 1 +cartoon/dog/pic_016.jpg 1 +cartoon/dog/pic_017.jpg 1 +cartoon/dog/pic_018.jpg 1 +cartoon/dog/pic_032.jpg 1 +cartoon/dog/pic_030.jpg 1 +cartoon/dog/pic_021.jpg 1 +cartoon/dog/pic_024.jpg 1 +cartoon/dog/pic_028.jpg 1 +cartoon/dog/pic_026.jpg 1 +cartoon/dog/pic_022.jpg 1 +cartoon/dog/pic_447.jpg 1 +cartoon/dog/pic_449.jpg 1 +cartoon/dog/pic_450.jpg 1 +cartoon/dog/pic_166.jpg 1 +cartoon/dog/pic_171.jpg 1 +cartoon/dog/pic_167.jpg 1 +cartoon/dog/pic_168.jpg 1 +cartoon/dog/pic_172.jpg 1 +cartoon/dog/pic_170.jpg 1 +cartoon/dog/pic_169.jpg 1 +cartoon/dog/pic_173.jpg 1 +cartoon/dog/pic_176.jpg 1 +cartoon/dog/pic_175.jpg 1 +cartoon/dog/pic_180.jpg 1 +cartoon/dog/pic_179.jpg 1 +cartoon/dog/pic_178.jpg 1 +cartoon/dog/pic_177.jpg 1 +cartoon/dog/pic_183.jpg 1 +cartoon/dog/pic_184.jpg 1 +cartoon/dog/pic_182.jpg 1 +cartoon/dog/pic_220.jpg 1 +cartoon/dog/pic_219.jpg 1 +cartoon/dog/pic_216.jpg 1 +cartoon/dog/pic_273.jpg 1 +cartoon/dog/pic_272.jpg 1 +cartoon/dog/pic_275.jpg 1 +cartoon/dog/pic_274.jpg 1 +cartoon/dog/pic_280.jpg 1 +cartoon/dog/pic_279.jpg 1 +cartoon/dog/pic_281.jpg 1 +cartoon/dog/pic_282.jpg 1 +cartoon/dog/pic_327.jpg 1 +cartoon/dog/pic_329.jpg 1 +cartoon/dog/pic_326.jpg 1 +cartoon/dog/pic_328.jpg 1 +cartoon/dog/pic_335.jpg 1 +cartoon/dog/pic_338.jpg 1 +cartoon/dog/pic_339.jpg 1 +cartoon/dog/pic_337.jpg 1 +cartoon/dog/pic_374.jpg 1 +cartoon/dog/pic_372.jpg 1 +cartoon/dog/pic_371.jpg 1 +cartoon/dog/pic_369.jpg 1 +cartoon/dog/pic_368.jpg 1 +cartoon/dog/pic_367.jpg 1 +cartoon/dog/pic_366.jpg 1 +cartoon/dog/pic_365.jpg 1 +cartoon/dog/pic_364.jpg 1 +cartoon/dog/pic_437.jpg 1 +cartoon/dog/pic_431.jpg 1 +cartoon/dog/pic_413.jpg 1 +cartoon/dog/pic_394.jpg 1 +cartoon/dog/pic_428.jpg 1 +cartoon/dog/pic_387.jpg 1 +cartoon/dog/pic_380.jpg 1 +cartoon/dog/pic_376.jpg 1 +cartoon/dog/pic_425.jpg 1 +cartoon/dog/pic_414.jpg 1 +cartoon/dog/pic_398.jpg 1 +cartoon/dog/pic_317.jpg 1 +cartoon/dog/pic_318.jpg 1 +cartoon/dog/pic_323.jpg 1 +cartoon/dog/pic_363.jpg 1 +cartoon/dog/pic_357.jpg 1 +cartoon/dog/pic_356.jpg 1 +cartoon/dog/pic_354.jpg 1 +cartoon/dog/pic_352.jpg 1 +cartoon/dog/pic_353.jpg 1 +cartoon/dog/pic_348.jpg 1 +cartoon/dog/pic_345.jpg 1 +cartoon/dog/pic_344.jpg 1 +cartoon/dog/pic_343.jpg 1 +cartoon/dog/pic_341.jpg 1 +cartoon/dog/pic_333.jpg 1 +cartoon/dog/pic_334.jpg 1 +cartoon/dog/pic_331.jpg 1 +cartoon/dog/pic_350.jpg 1 +cartoon/dog/pic_181.jpg 1 +cartoon/dog/pic_188.jpg 1 +cartoon/dog/pic_190.jpg 1 +cartoon/dog/pic_186.jpg 1 +cartoon/dog/pic_185.jpg 1 +cartoon/dog/pic_189.jpg 1 +cartoon/dog/pic_192.jpg 1 +cartoon/dog/pic_191.jpg 1 +cartoon/dog/pic_193.jpg 1 +cartoon/dog/pic_195.jpg 1 +cartoon/dog/pic_201.jpg 1 +cartoon/dog/pic_200.jpg 1 +cartoon/dog/pic_197.jpg 1 +cartoon/dog/pic_198.jpg 1 +cartoon/dog/pic_196.jpg 1 +cartoon/dog/pic_202.jpg 1 +cartoon/dog/pic_204.jpg 1 +cartoon/dog/pic_203.jpg 1 +cartoon/dog/pic_034.jpg 1 +cartoon/dog/pic_027.jpg 1 +cartoon/dog/pic_029.jpg 1 +cartoon/dog/pic_050.jpg 1 +cartoon/dog/pic_035.jpg 1 +cartoon/dog/pic_037.jpg 1 +cartoon/dog/pic_051.jpg 1 +cartoon/dog/pic_045.jpg 1 +cartoon/dog/pic_058.jpg 1 +cartoon/dog/pic_057.jpg 1 +cartoon/dog/pic_059.jpg 1 +cartoon/dog/pic_062.jpg 1 +cartoon/dog/pic_063.jpg 1 +cartoon/dog/pic_060.jpg 1 +cartoon/dog/pic_061.jpg 1 +cartoon/dog/pic_065.jpg 1 +cartoon/dog/pic_064.jpg 1 +cartoon/dog/pic_068.jpg 1 +cartoon/dog/pic_067.jpg 1 +cartoon/dog/pic_432.jpg 1 +cartoon/dog/pic_424.jpg 1 +cartoon/dog/pic_445.jpg 1 +cartoon/dog/pic_397.jpg 1 +cartoon/dog/pic_389.jpg 1 +cartoon/dog/pic_395.jpg 1 +cartoon/dog/pic_435.jpg 1 +cartoon/dog/pic_399.jpg 1 +cartoon/dog/pic_411.jpg 1 +cartoon/dog/pic_434.jpg 1 +cartoon/dog/pic_444.jpg 1 +cartoon/dog/pic_401.jpg 1 +cartoon/dog/pic_396.jpg 1 +cartoon/dog/pic_426.jpg 1 +cartoon/dog/pic_433.jpg 1 +cartoon/dog/pic_443.jpg 1 +cartoon/dog/pic_412.jpg 1 +cartoon/dog/pic_148.jpg 1 +cartoon/dog/pic_146.jpg 1 +cartoon/dog/pic_418.jpg 1 +cartoon/dog/pic_156.jpg 1 +cartoon/dog/pic_149.jpg 1 +cartoon/dog/pic_160.jpg 1 +cartoon/dog/pic_161.jpg 1 +cartoon/dog/pic_163.jpg 1 +cartoon/dog/pic_165.jpg 1 +cartoon/dog/pic_164.jpg 1 +cartoon/dog/pic_419.jpg 1 +cartoon/dog/pic_422.jpg 1 +cartoon/dog/pic_420.jpg 1 +cartoon/dog/pic_421.jpg 1 +cartoon/dog/pic_423.jpg 1 +cartoon/dog/pic_439.jpg 1 +cartoon/dog/pic_438.jpg 1 +cartoon/dog/pic_441.jpg 1 +cartoon/dog/pic_440.jpg 1 +cartoon/dog/pic_242.jpg 1 +cartoon/dog/pic_260.jpg 1 +cartoon/dog/pic_293.jpg 1 +cartoon/dog/pic_278.jpg 1 +cartoon/dog/pic_269.jpg 1 +cartoon/dog/pic_292.jpg 1 +cartoon/dog/pic_268.jpg 1 +cartoon/dog/pic_291.jpg 1 +cartoon/dog/pic_289.jpg 1 +cartoon/dog/pic_266.jpg 1 +cartoon/dog/pic_258.jpg 1 +cartoon/dog/pic_264.jpg 1 +cartoon/dog/pic_287.jpg 1 +cartoon/dog/pic_298.jpg 1 +cartoon/dog/pic_288.jpg 1 +cartoon/dog/pic_295.jpg 1 +cartoon/dog/pic_299.jpg 1 +cartoon/dog/pic_306.jpg 1 +cartoon/dog/pic_305.jpg 1 +cartoon/dog/pic_304.jpg 1 +cartoon/dog/pic_302.jpg 1 +cartoon/dog/pic_303.jpg 1 +cartoon/dog/pic_308.jpg 1 +cartoon/dog/pic_309.jpg 1 +cartoon/dog/pic_330.jpg 1 +cartoon/dog/pic_324.jpg 1 +cartoon/dog/pic_322.jpg 1 +cartoon/dog/pic_319.jpg 1 +cartoon/dog/pic_320.jpg 1 +cartoon/dog/pic_315.jpg 1 +cartoon/dog/pic_313.jpg 1 +cartoon/dog/pic_314.jpg 1 +cartoon/dog/pic_310.jpg 1 +cartoon/dog/pic_325.jpg 1 +cartoon/dog/pic_316.jpg 1 +cartoon/dog/pic_321.jpg 1 +cartoon/dog/pic_312.jpg 1 +cartoon/dog/pic_069.jpg 1 +cartoon/dog/pic_066.jpg 1 +cartoon/dog/pic_082.jpg 1 +cartoon/dog/pic_078.jpg 1 +cartoon/dog/pic_076.jpg 1 +cartoon/dog/pic_077.jpg 1 +cartoon/dog/pic_074.jpg 1 +cartoon/dog/pic_073.jpg 1 +cartoon/dog/pic_072.jpg 1 +cartoon/dog/pic_071.jpg 1 +cartoon/dog/pic_079.jpg 1 +cartoon/dog/pic_080.jpg 1 +cartoon/dog/pic_083.jpg 1 +cartoon/dog/pic_081.jpg 1 +cartoon/dog/pic_084.jpg 1 +cartoon/dog/pic_085.jpg 1 +cartoon/dog/pic_086.jpg 1 +cartoon/dog/pic_087.jpg 1 +cartoon/dog/pic_088.jpg 1 +cartoon/dog/pic_089.jpg 1 +cartoon/dog/pic_090.jpg 1 +cartoon/dog/pic_094.jpg 1 +cartoon/dog/pic_093.jpg 1 +cartoon/dog/pic_091.jpg 1 +cartoon/dog/pic_092.jpg 1 +cartoon/dog/pic_108.jpg 1 +cartoon/dog/pic_105.jpg 1 +cartoon/dog/pic_104.jpg 1 +cartoon/dog/pic_103.jpg 1 +cartoon/dog/pic_099.jpg 1 +cartoon/dog/pic_101.jpg 1 +cartoon/dog/pic_098.jpg 1 +cartoon/dog/pic_097.jpg 1 +cartoon/dog/pic_096.jpg 1 +cartoon/dog/pic_095.jpg 1 +cartoon/dog/pic_102.jpg 1 +cartoon/dog/pic_106.jpg 1 +cartoon/dog/pic_107.jpg 1 +cartoon/dog/pic_100.jpg 1 +cartoon/dog/pic_113.jpg 1 +cartoon/dog/pic_110.jpg 1 +cartoon/elephant/pic_211.jpg 2 +cartoon/elephant/pic_154.jpg 2 +cartoon/elephant/pic_153.jpg 2 +cartoon/elephant/pic_237.jpg 2 +cartoon/elephant/pic_227.jpg 2 +cartoon/elephant/pic_226.jpg 2 +cartoon/elephant/pic_225.jpg 2 +cartoon/elephant/pic_155.jpg 2 +cartoon/elephant/pic_165.jpg 2 +cartoon/elephant/pic_164.jpg 2 +cartoon/elephant/pic_162.jpg 2 +cartoon/elephant/pic_157.jpg 2 +cartoon/elephant/pic_156.jpg 2 +cartoon/elephant/pic_166.jpg 2 +cartoon/elephant/pic_168.jpg 2 +cartoon/elephant/pic_167.jpg 2 +cartoon/elephant/pic_169.jpg 2 +cartoon/elephant/pic_171.jpg 2 +cartoon/elephant/pic_170.jpg 2 +cartoon/elephant/pic_240.jpg 2 +cartoon/elephant/pic_243.jpg 2 +cartoon/elephant/pic_242.jpg 2 +cartoon/elephant/pic_244.jpg 2 +cartoon/elephant/pic_172.jpg 2 +cartoon/elephant/pic_247.jpg 2 +cartoon/elephant/pic_248.jpg 2 +cartoon/elephant/pic_251.jpg 2 +cartoon/elephant/pic_250.jpg 2 +cartoon/elephant/pic_249.jpg 2 +cartoon/elephant/pic_252.jpg 2 +cartoon/elephant/pic_258.jpg 2 +cartoon/elephant/pic_257.jpg 2 +cartoon/elephant/pic_173.jpg 2 +cartoon/elephant/pic_412.jpg 2 +cartoon/elephant/pic_411.jpg 2 +cartoon/elephant/pic_408.jpg 2 +cartoon/elephant/pic_409.jpg 2 +cartoon/elephant/pic_413.jpg 2 +cartoon/elephant/pic_410.jpg 2 +cartoon/elephant/pic_431.jpg 2 +cartoon/elephant/pic_430.jpg 2 +cartoon/elephant/pic_428.jpg 2 +cartoon/elephant/pic_425.jpg 2 +cartoon/elephant/pic_423.jpg 2 +cartoon/elephant/pic_424.jpg 2 +cartoon/elephant/pic_420.jpg 2 +cartoon/elephant/pic_421.jpg 2 +cartoon/elephant/pic_419.jpg 2 +cartoon/elephant/pic_418.jpg 2 +cartoon/elephant/pic_026.jpg 2 +cartoon/elephant/pic_028.jpg 2 +cartoon/elephant/pic_024.jpg 2 +cartoon/elephant/pic_027.jpg 2 +cartoon/elephant/pic_021.jpg 2 +cartoon/elephant/pic_030.jpg 2 +cartoon/elephant/pic_036.jpg 2 +cartoon/elephant/pic_037.jpg 2 +cartoon/elephant/pic_033.jpg 2 +cartoon/elephant/pic_056.jpg 2 +cartoon/elephant/pic_052.jpg 2 +cartoon/elephant/pic_048.jpg 2 +cartoon/elephant/pic_040.jpg 2 +cartoon/elephant/pic_046.jpg 2 +cartoon/elephant/pic_045.jpg 2 +cartoon/elephant/pic_043.jpg 2 +cartoon/elephant/pic_044.jpg 2 +cartoon/elephant/pic_042.jpg 2 +cartoon/elephant/pic_034.jpg 2 +cartoon/elephant/pic_025.jpg 2 +cartoon/elephant/pic_325.jpg 2 +cartoon/elephant/pic_328.jpg 2 +cartoon/elephant/pic_329.jpg 2 +cartoon/elephant/pic_330.jpg 2 +cartoon/elephant/pic_331.jpg 2 +cartoon/elephant/pic_332.jpg 2 +cartoon/elephant/pic_333.jpg 2 +cartoon/elephant/pic_338.jpg 2 +cartoon/elephant/pic_336.jpg 2 +cartoon/elephant/pic_337.jpg 2 +cartoon/elephant/pic_335.jpg 2 +cartoon/elephant/pic_334.jpg 2 +cartoon/elephant/pic_342.jpg 2 +cartoon/elephant/pic_339.jpg 2 +cartoon/elephant/pic_340.jpg 2 +cartoon/elephant/pic_341.jpg 2 +cartoon/elephant/pic_343.jpg 2 +cartoon/elephant/pic_351.jpg 2 +cartoon/elephant/pic_345.jpg 2 +cartoon/elephant/pic_350.jpg 2 +cartoon/elephant/pic_280.jpg 2 +cartoon/elephant/pic_203.jpg 2 +cartoon/elephant/pic_204.jpg 2 +cartoon/elephant/pic_215.jpg 2 +cartoon/elephant/pic_207.jpg 2 +cartoon/elephant/pic_208.jpg 2 +cartoon/elephant/pic_206.jpg 2 +cartoon/elephant/pic_205.jpg 2 +cartoon/elephant/pic_216.jpg 2 +cartoon/elephant/pic_223.jpg 2 +cartoon/elephant/pic_222.jpg 2 +cartoon/elephant/pic_221.jpg 2 +cartoon/elephant/pic_285.jpg 2 +cartoon/elephant/pic_282.jpg 2 +cartoon/elephant/pic_218.jpg 2 +cartoon/elephant/pic_217.jpg 2 +cartoon/elephant/pic_224.jpg 2 +cartoon/elephant/pic_286.jpg 2 +cartoon/elephant/pic_392.jpg 2 +cartoon/elephant/pic_390.jpg 2 +cartoon/elephant/pic_395.jpg 2 +cartoon/elephant/pic_393.jpg 2 +cartoon/elephant/pic_391.jpg 2 +cartoon/elephant/pic_394.jpg 2 +cartoon/elephant/pic_403.jpg 2 +cartoon/elephant/pic_401.jpg 2 +cartoon/elephant/pic_400.jpg 2 +cartoon/elephant/pic_399.jpg 2 +cartoon/elephant/pic_396.jpg 2 +cartoon/elephant/pic_397.jpg 2 +cartoon/elephant/pic_398.jpg 2 +cartoon/elephant/pic_402.jpg 2 +cartoon/elephant/pic_407.jpg 2 +cartoon/elephant/pic_406.jpg 2 +cartoon/elephant/pic_405.jpg 2 +cartoon/elephant/pic_404.jpg 2 +cartoon/elephant/pic_415.jpg 2 +cartoon/elephant/pic_416.jpg 2 +cartoon/elephant/pic_349.jpg 2 +cartoon/elephant/pic_348.jpg 2 +cartoon/elephant/pic_347.jpg 2 +cartoon/elephant/pic_346.jpg 2 +cartoon/elephant/pic_344.jpg 2 +cartoon/elephant/pic_356.jpg 2 +cartoon/elephant/pic_355.jpg 2 +cartoon/elephant/pic_354.jpg 2 +cartoon/elephant/pic_352.jpg 2 +cartoon/elephant/pic_359.jpg 2 +cartoon/elephant/pic_357.jpg 2 +cartoon/elephant/pic_362.jpg 2 +cartoon/elephant/pic_360.jpg 2 +cartoon/elephant/pic_366.jpg 2 +cartoon/elephant/pic_365.jpg 2 +cartoon/elephant/pic_364.jpg 2 +cartoon/elephant/pic_363.jpg 2 +cartoon/elephant/pic_367.jpg 2 +cartoon/elephant/pic_064.jpg 2 +cartoon/elephant/pic_063.jpg 2 +cartoon/elephant/pic_062.jpg 2 +cartoon/elephant/pic_061.jpg 2 +cartoon/elephant/pic_118.jpg 2 +cartoon/elephant/pic_111.jpg 2 +cartoon/elephant/pic_100.jpg 2 +cartoon/elephant/pic_098.jpg 2 +cartoon/elephant/pic_096.jpg 2 +cartoon/elephant/pic_092.jpg 2 +cartoon/elephant/pic_088.jpg 2 +cartoon/elephant/pic_086.jpg 2 +cartoon/elephant/pic_083.jpg 2 +cartoon/elephant/pic_080.jpg 2 +cartoon/elephant/pic_079.jpg 2 +cartoon/elephant/pic_078.jpg 2 +cartoon/elephant/pic_076.jpg 2 +cartoon/elephant/pic_068.jpg 2 +cartoon/elephant/pic_072.jpg 2 +cartoon/elephant/pic_074.jpg 2 +cartoon/elephant/pic_071.jpg 2 +cartoon/elephant/pic_001.jpg 2 +cartoon/elephant/pic_002.jpg 2 +cartoon/elephant/pic_003.jpg 2 +cartoon/elephant/pic_004.jpg 2 +cartoon/elephant/pic_005.jpg 2 +cartoon/elephant/pic_007.jpg 2 +cartoon/elephant/pic_008.jpg 2 +cartoon/elephant/pic_009.jpg 2 +cartoon/elephant/pic_010.jpg 2 +cartoon/elephant/pic_011.jpg 2 +cartoon/elephant/pic_012.jpg 2 +cartoon/elephant/pic_013.jpg 2 +cartoon/elephant/pic_014.jpg 2 +cartoon/elephant/pic_015.jpg 2 +cartoon/elephant/pic_016.jpg 2 +cartoon/elephant/pic_017.jpg 2 +cartoon/elephant/pic_019.jpg 2 +cartoon/elephant/pic_020.jpg 2 +cartoon/elephant/pic_038.jpg 2 +cartoon/elephant/pic_220.jpg 2 +cartoon/elephant/pic_219.jpg 2 +cartoon/elephant/pic_284.jpg 2 +cartoon/elephant/pic_233.jpg 2 +cartoon/elephant/pic_232.jpg 2 +cartoon/elephant/pic_290.jpg 2 +cartoon/elephant/pic_292.jpg 2 +cartoon/elephant/pic_231.jpg 2 +cartoon/elephant/pic_228.jpg 2 +cartoon/elephant/pic_230.jpg 2 +cartoon/elephant/pic_229.jpg 2 +cartoon/elephant/pic_289.jpg 2 +cartoon/elephant/pic_291.jpg 2 +cartoon/elephant/pic_236.jpg 2 +cartoon/elephant/pic_235.jpg 2 +cartoon/elephant/pic_294.jpg 2 +cartoon/elephant/pic_239.jpg 2 +cartoon/elephant/pic_238.jpg 2 +cartoon/elephant/pic_295.jpg 2 +cartoon/elephant/pic_296.jpg 2 +cartoon/elephant/pic_183.jpg 2 +cartoon/elephant/pic_182.jpg 2 +cartoon/elephant/pic_190.jpg 2 +cartoon/elephant/pic_198.jpg 2 +cartoon/elephant/pic_197.jpg 2 +cartoon/elephant/pic_196.jpg 2 +cartoon/elephant/pic_273.jpg 2 +cartoon/elephant/pic_194.jpg 2 +cartoon/elephant/pic_272.jpg 2 +cartoon/elephant/pic_195.jpg 2 +cartoon/elephant/pic_192.jpg 2 +cartoon/elephant/pic_276.jpg 2 +cartoon/elephant/pic_279.jpg 2 +cartoon/elephant/pic_202.jpg 2 +cartoon/elephant/pic_275.jpg 2 +cartoon/elephant/pic_274.jpg 2 +cartoon/elephant/pic_200.jpg 2 +cartoon/elephant/pic_201.jpg 2 +cartoon/elephant/pic_199.jpg 2 +cartoon/elephant/pic_433.jpg 2 +cartoon/elephant/pic_434.jpg 2 +cartoon/elephant/pic_435.jpg 2 +cartoon/elephant/pic_432.jpg 2 +cartoon/elephant/pic_439.jpg 2 +cartoon/elephant/pic_427.jpg 2 +cartoon/elephant/pic_440.jpg 2 +cartoon/elephant/pic_438.jpg 2 +cartoon/elephant/pic_426.jpg 2 +cartoon/elephant/pic_449.jpg 2 +cartoon/elephant/pic_447.jpg 2 +cartoon/elephant/pic_448.jpg 2 +cartoon/elephant/pic_444.jpg 2 +cartoon/elephant/pic_443.jpg 2 +cartoon/elephant/pic_442.jpg 2 +cartoon/elephant/pic_446.jpg 2 +cartoon/elephant/pic_464.jpg 2 +cartoon/elephant/pic_368.jpg 2 +cartoon/elephant/pic_370.jpg 2 +cartoon/elephant/pic_372.jpg 2 +cartoon/elephant/pic_373.jpg 2 +cartoon/elephant/pic_374.jpg 2 +cartoon/elephant/pic_376.jpg 2 +cartoon/elephant/pic_375.jpg 2 +cartoon/elephant/pic_378.jpg 2 +cartoon/elephant/pic_377.jpg 2 +cartoon/elephant/pic_381.jpg 2 +cartoon/elephant/pic_382.jpg 2 +cartoon/elephant/pic_383.jpg 2 +cartoon/elephant/pic_384.jpg 2 +cartoon/elephant/pic_385.jpg 2 +cartoon/elephant/pic_389.jpg 2 +cartoon/elephant/pic_388.jpg 2 +cartoon/elephant/pic_387.jpg 2 +cartoon/elephant/pic_023.jpg 2 +cartoon/elephant/pic_022.jpg 2 +cartoon/elephant/pic_039.jpg 2 +cartoon/elephant/pic_053.jpg 2 +cartoon/elephant/pic_049.jpg 2 +cartoon/elephant/pic_047.jpg 2 +cartoon/elephant/pic_041.jpg 2 +cartoon/elephant/pic_050.jpg 2 +cartoon/elephant/pic_035.jpg 2 +cartoon/elephant/pic_057.jpg 2 +cartoon/elephant/pic_032.jpg 2 +cartoon/elephant/pic_055.jpg 2 +cartoon/elephant/pic_058.jpg 2 +cartoon/elephant/pic_029.jpg 2 +cartoon/elephant/pic_051.jpg 2 +cartoon/elephant/pic_054.jpg 2 +cartoon/elephant/pic_059.jpg 2 +cartoon/elephant/pic_060.jpg 2 +cartoon/elephant/pic_066.jpg 2 +cartoon/elephant/pic_065.jpg 2 +cartoon/elephant/pic_085.jpg 2 +cartoon/elephant/pic_094.jpg 2 +cartoon/elephant/pic_091.jpg 2 +cartoon/elephant/pic_110.jpg 2 +cartoon/elephant/pic_147.jpg 2 +cartoon/elephant/pic_149.jpg 2 +cartoon/elephant/pic_140.jpg 2 +cartoon/elephant/pic_135.jpg 2 +cartoon/elephant/pic_115.jpg 2 +cartoon/elephant/pic_089.jpg 2 +cartoon/elephant/pic_107.jpg 2 +cartoon/elephant/pic_104.jpg 2 +cartoon/elephant/pic_095.jpg 2 +cartoon/elephant/pic_142.jpg 2 +cartoon/elephant/pic_081.jpg 2 +cartoon/elephant/pic_090.jpg 2 +cartoon/elephant/pic_097.jpg 2 +cartoon/elephant/pic_106.jpg 2 +cartoon/elephant/pic_151.jpg 2 +cartoon/elephant/pic_129.jpg 2 +cartoon/elephant/pic_121.jpg 2 +cartoon/elephant/pic_259.jpg 2 +cartoon/elephant/pic_174.jpg 2 +cartoon/elephant/pic_260.jpg 2 +cartoon/elephant/pic_180.jpg 2 +cartoon/elephant/pic_178.jpg 2 +cartoon/elephant/pic_177.jpg 2 +cartoon/elephant/pic_176.jpg 2 +cartoon/elephant/pic_264.jpg 2 +cartoon/elephant/pic_175.jpg 2 +cartoon/elephant/pic_263.jpg 2 +cartoon/elephant/pic_262.jpg 2 +cartoon/elephant/pic_261.jpg 2 +cartoon/elephant/pic_181.jpg 2 +cartoon/elephant/pic_268.jpg 2 +cartoon/elephant/pic_179.jpg 2 +cartoon/elephant/pic_269.jpg 2 +cartoon/elephant/pic_191.jpg 2 +cartoon/elephant/pic_271.jpg 2 +cartoon/elephant/pic_184.jpg 2 +cartoon/elephant/pic_185.jpg 2 +cartoon/elephant/pic_270.jpg 2 +cartoon/elephant/pic_070.jpg 2 +cartoon/elephant/pic_067.jpg 2 +cartoon/elephant/pic_069.jpg 2 +cartoon/elephant/pic_137.jpg 2 +cartoon/elephant/pic_136.jpg 2 +cartoon/elephant/pic_108.jpg 2 +cartoon/elephant/pic_116.jpg 2 +cartoon/elephant/pic_117.jpg 2 +cartoon/elephant/pic_103.jpg 2 +cartoon/elephant/pic_093.jpg 2 +cartoon/elephant/pic_099.jpg 2 +cartoon/elephant/pic_084.jpg 2 +cartoon/elephant/pic_102.jpg 2 +cartoon/elephant/pic_087.jpg 2 +cartoon/elephant/pic_082.jpg 2 +cartoon/elephant/pic_073.jpg 2 +cartoon/elephant/pic_075.jpg 2 +cartoon/elephant/pic_077.jpg 2 +cartoon/elephant/pic_473.jpg 2 +cartoon/elephant/pic_475.jpg 2 +cartoon/elephant/pic_474.jpg 2 +cartoon/elephant/pic_476.jpg 2 +cartoon/elephant/pic_481.jpg 2 +cartoon/elephant/pic_480.jpg 2 +cartoon/elephant/pic_478.jpg 2 +cartoon/elephant/pic_479.jpg 2 +cartoon/elephant/pic_477.jpg 2 +cartoon/elephant/pic_482.jpg 2 +cartoon/elephant/pic_485.jpg 2 +cartoon/elephant/pic_484.jpg 2 +cartoon/elephant/pic_483.jpg 2 +cartoon/elephant/pic_486.jpg 2 +cartoon/elephant/pic_487.jpg 2 +cartoon/elephant/pic_491.jpg 2 +cartoon/elephant/pic_493.jpg 2 +cartoon/elephant/pic_305.jpg 2 +cartoon/elephant/pic_307.jpg 2 +cartoon/elephant/pic_311.jpg 2 +cartoon/elephant/pic_308.jpg 2 +cartoon/elephant/pic_312.jpg 2 +cartoon/elephant/pic_310.jpg 2 +cartoon/elephant/pic_313.jpg 2 +cartoon/elephant/pic_309.jpg 2 +cartoon/elephant/pic_314.jpg 2 +cartoon/elephant/pic_316.jpg 2 +cartoon/elephant/pic_319.jpg 2 +cartoon/elephant/pic_318.jpg 2 +cartoon/elephant/pic_322.jpg 2 +cartoon/elephant/pic_320.jpg 2 +cartoon/elephant/pic_324.jpg 2 +cartoon/elephant/pic_323.jpg 2 +cartoon/elephant/pic_327.jpg 2 +cartoon/elephant/pic_326.jpg 2 +cartoon/elephant/pic_114.jpg 2 +cartoon/elephant/pic_146.jpg 2 +cartoon/elephant/pic_131.jpg 2 +cartoon/elephant/pic_132.jpg 2 +cartoon/elephant/pic_213.jpg 2 +cartoon/elephant/pic_210.jpg 2 +cartoon/elephant/pic_186.jpg 2 +cartoon/elephant/pic_188.jpg 2 +cartoon/elephant/pic_214.jpg 2 +cartoon/elephant/pic_152.jpg 2 +cartoon/elephant/pic_119.jpg 2 +cartoon/elephant/pic_133.jpg 2 +cartoon/elephant/pic_139.jpg 2 +cartoon/elephant/pic_212.jpg 2 +cartoon/elephant/pic_209.jpg 2 +cartoon/elephant/pic_126.jpg 2 +cartoon/elephant/pic_130.jpg 2 +cartoon/elephant/pic_187.jpg 2 +cartoon/elephant/pic_159.jpg 2 +cartoon/elephant/pic_462.jpg 2 +cartoon/elephant/pic_463.jpg 2 +cartoon/elephant/pic_460.jpg 2 +cartoon/elephant/pic_461.jpg 2 +cartoon/elephant/pic_458.jpg 2 +cartoon/elephant/pic_456.jpg 2 +cartoon/elephant/pic_454.jpg 2 +cartoon/elephant/pic_453.jpg 2 +cartoon/elephant/pic_452.jpg 2 +cartoon/elephant/pic_450.jpg 2 +cartoon/elephant/pic_468.jpg 2 +cartoon/elephant/pic_459.jpg 2 +cartoon/elephant/pic_455.jpg 2 +cartoon/elephant/pic_457.jpg 2 +cartoon/elephant/pic_466.jpg 2 +cartoon/elephant/pic_465.jpg 2 +cartoon/elephant/pic_471.jpg 2 +cartoon/elephant/pic_469.jpg 2 +cartoon/elephant/pic_496.jpg 2 +cartoon/elephant/pic_495.jpg 2 +cartoon/elephant/pic_497.jpg 2 +cartoon/elephant/pic_498.jpg 2 +cartoon/elephant/pic_499.jpg 2 +cartoon/elephant/pic_502.jpg 2 +cartoon/elephant/pic_504.jpg 2 +cartoon/elephant/pic_501.jpg 2 +cartoon/elephant/pic_505.jpg 2 +cartoon/elephant/pic_245.jpg 2 +cartoon/elephant/pic_246.jpg 2 +cartoon/elephant/pic_253.jpg 2 +cartoon/elephant/pic_299.jpg 2 +cartoon/elephant/pic_278.jpg 2 +cartoon/elephant/pic_288.jpg 2 +cartoon/elephant/pic_304.jpg 2 +cartoon/elephant/pic_303.jpg 2 +cartoon/elephant/pic_266.jpg 2 +cartoon/elephant/pic_265.jpg 2 +cartoon/elephant/pic_256.jpg 2 +cartoon/elephant/pic_254.jpg 2 +cartoon/elephant/pic_255.jpg 2 +cartoon/elephant/pic_306.jpg 2 +cartoon/elephant/pic_293.jpg 2 +cartoon/elephant/pic_302.jpg 2 +cartoon/elephant/pic_301.jpg 2 +cartoon/elephant/pic_300.jpg 2 +cartoon/elephant/pic_138.jpg 2 +cartoon/elephant/pic_125.jpg 2 +cartoon/elephant/pic_112.jpg 2 +cartoon/elephant/pic_144.jpg 2 +cartoon/elephant/pic_101.jpg 2 +cartoon/elephant/pic_122.jpg 2 +cartoon/elephant/pic_120.jpg 2 +cartoon/elephant/pic_105.jpg 2 +cartoon/elephant/pic_189.jpg 2 +cartoon/elephant/pic_141.jpg 2 +cartoon/elephant/pic_143.jpg 2 +cartoon/elephant/pic_160.jpg 2 +cartoon/elephant/pic_113.jpg 2 +cartoon/elephant/pic_145.jpg 2 +cartoon/elephant/pic_109.jpg 2 +cartoon/elephant/pic_148.jpg 2 +cartoon/elephant/pic_128.jpg 2 +cartoon/elephant/pic_127.jpg 2 +cartoon/elephant/pic_150.jpg 2 +cartoon/elephant/pic_124.jpg 2 +cartoon/giraffe/pic_005.jpg 3 +cartoon/giraffe/pic_006.jpg 3 +cartoon/giraffe/pic_007.jpg 3 +cartoon/giraffe/pic_008.jpg 3 +cartoon/giraffe/pic_009.jpg 3 +cartoon/giraffe/pic_010.jpg 3 +cartoon/giraffe/pic_011.jpg 3 +cartoon/giraffe/pic_012.jpg 3 +cartoon/giraffe/pic_013.jpg 3 +cartoon/giraffe/pic_014.jpg 3 +cartoon/giraffe/pic_015.jpg 3 +cartoon/giraffe/pic_016.jpg 3 +cartoon/giraffe/pic_017.jpg 3 +cartoon/giraffe/pic_018.jpg 3 +cartoon/giraffe/pic_019.jpg 3 +cartoon/giraffe/pic_020.jpg 3 +cartoon/giraffe/pic_022.jpg 3 +cartoon/giraffe/pic_025.jpg 3 +cartoon/giraffe/pic_024.jpg 3 +cartoon/giraffe/pic_091.jpg 3 +cartoon/giraffe/pic_090.jpg 3 +cartoon/giraffe/pic_087.jpg 3 +cartoon/giraffe/pic_086.jpg 3 +cartoon/giraffe/pic_085.jpg 3 +cartoon/giraffe/pic_095.jpg 3 +cartoon/giraffe/pic_096.jpg 3 +cartoon/giraffe/pic_093.jpg 3 +cartoon/giraffe/pic_094.jpg 3 +cartoon/giraffe/pic_106.jpg 3 +cartoon/giraffe/pic_108.jpg 3 +cartoon/giraffe/pic_104.jpg 3 +cartoon/giraffe/pic_103.jpg 3 +cartoon/giraffe/pic_101.jpg 3 +cartoon/giraffe/pic_100.jpg 3 +cartoon/giraffe/pic_099.jpg 3 +cartoon/giraffe/pic_098.jpg 3 +cartoon/giraffe/pic_097.jpg 3 +cartoon/giraffe/pic_107.jpg 3 +cartoon/giraffe/pic_109.jpg 3 +cartoon/giraffe/pic_285.jpg 3 +cartoon/giraffe/pic_282.jpg 3 +cartoon/giraffe/pic_284.jpg 3 +cartoon/giraffe/pic_287.jpg 3 +cartoon/giraffe/pic_286.jpg 3 +cartoon/giraffe/pic_298.jpg 3 +cartoon/giraffe/pic_296.jpg 3 +cartoon/giraffe/pic_294.jpg 3 +cartoon/giraffe/pic_293.jpg 3 +cartoon/giraffe/pic_292.jpg 3 +cartoon/giraffe/pic_290.jpg 3 +cartoon/giraffe/pic_288.jpg 3 +cartoon/giraffe/pic_291.jpg 3 +cartoon/giraffe/pic_320.jpg 3 +cartoon/giraffe/pic_313.jpg 3 +cartoon/giraffe/pic_305.jpg 3 +cartoon/giraffe/pic_307.jpg 3 +cartoon/giraffe/pic_306.jpg 3 +cartoon/giraffe/pic_303.jpg 3 +cartoon/giraffe/pic_152.jpg 3 +cartoon/giraffe/pic_153.jpg 3 +cartoon/giraffe/pic_151.jpg 3 +cartoon/giraffe/pic_155.jpg 3 +cartoon/giraffe/pic_156.jpg 3 +cartoon/giraffe/pic_157.jpg 3 +cartoon/giraffe/pic_159.jpg 3 +cartoon/giraffe/pic_160.jpg 3 +cartoon/giraffe/pic_161.jpg 3 +cartoon/giraffe/pic_162.jpg 3 +cartoon/giraffe/pic_158.jpg 3 +cartoon/giraffe/pic_163.jpg 3 +cartoon/giraffe/pic_164.jpg 3 +cartoon/giraffe/pic_165.jpg 3 +cartoon/giraffe/pic_166.jpg 3 +cartoon/giraffe/pic_167.jpg 3 +cartoon/giraffe/pic_168.jpg 3 +cartoon/giraffe/pic_170.jpg 3 +cartoon/giraffe/pic_369.jpg 3 +cartoon/giraffe/pic_368.jpg 3 +cartoon/giraffe/pic_367.jpg 3 +cartoon/giraffe/pic_365.jpg 3 +cartoon/giraffe/pic_364.jpg 3 +cartoon/giraffe/pic_363.jpg 3 +cartoon/giraffe/pic_373.jpg 3 +cartoon/giraffe/pic_370.jpg 3 +cartoon/giraffe/pic_376.jpg 3 +cartoon/giraffe/pic_375.jpg 3 +cartoon/giraffe/pic_377.jpg 3 +cartoon/giraffe/pic_379.jpg 3 +cartoon/giraffe/pic_381.jpg 3 +cartoon/giraffe/pic_382.jpg 3 +cartoon/giraffe/pic_380.jpg 3 +cartoon/giraffe/pic_383.jpg 3 +cartoon/giraffe/pic_385.jpg 3 +cartoon/giraffe/pic_384.jpg 3 +cartoon/giraffe/pic_386.jpg 3 +cartoon/giraffe/pic_031.jpg 3 +cartoon/giraffe/pic_030.jpg 3 +cartoon/giraffe/pic_029.jpg 3 +cartoon/giraffe/pic_027.jpg 3 +cartoon/giraffe/pic_023.jpg 3 +cartoon/giraffe/pic_026.jpg 3 +cartoon/giraffe/pic_033.jpg 3 +cartoon/giraffe/pic_028.jpg 3 +cartoon/giraffe/pic_032.jpg 3 +cartoon/giraffe/pic_043.jpg 3 +cartoon/giraffe/pic_042.jpg 3 +cartoon/giraffe/pic_041.jpg 3 +cartoon/giraffe/pic_039.jpg 3 +cartoon/giraffe/pic_038.jpg 3 +cartoon/giraffe/pic_036.jpg 3 +cartoon/giraffe/pic_035.jpg 3 +cartoon/giraffe/pic_037.jpg 3 +cartoon/giraffe/pic_040.jpg 3 +cartoon/giraffe/pic_051.jpg 3 +cartoon/giraffe/pic_050.jpg 3 +cartoon/giraffe/pic_048.jpg 3 +cartoon/giraffe/pic_047.jpg 3 +cartoon/giraffe/pic_045.jpg 3 +cartoon/giraffe/pic_044.jpg 3 +cartoon/giraffe/pic_053.jpg 3 +cartoon/giraffe/pic_052.jpg 3 +cartoon/giraffe/pic_054.jpg 3 +cartoon/giraffe/pic_056.jpg 3 +cartoon/giraffe/pic_055.jpg 3 +cartoon/giraffe/pic_057.jpg 3 +cartoon/giraffe/pic_059.jpg 3 +cartoon/giraffe/pic_060.jpg 3 +cartoon/giraffe/pic_058.jpg 3 +cartoon/giraffe/pic_062.jpg 3 +cartoon/giraffe/pic_061.jpg 3 +cartoon/giraffe/pic_067.jpg 3 +cartoon/giraffe/pic_064.jpg 3 +cartoon/giraffe/pic_065.jpg 3 +cartoon/giraffe/pic_066.jpg 3 +cartoon/giraffe/pic_233.jpg 3 +cartoon/giraffe/pic_235.jpg 3 +cartoon/giraffe/pic_236.jpg 3 +cartoon/giraffe/pic_238.jpg 3 +cartoon/giraffe/pic_237.jpg 3 +cartoon/giraffe/pic_239.jpg 3 +cartoon/giraffe/pic_130.jpg 3 +cartoon/giraffe/pic_131.jpg 3 +cartoon/giraffe/pic_134.jpg 3 +cartoon/giraffe/pic_133.jpg 3 +cartoon/giraffe/pic_132.jpg 3 +cartoon/giraffe/pic_136.jpg 3 +cartoon/giraffe/pic_138.jpg 3 +cartoon/giraffe/pic_139.jpg 3 +cartoon/giraffe/pic_141.jpg 3 +cartoon/giraffe/pic_143.jpg 3 +cartoon/giraffe/pic_145.jpg 3 +cartoon/giraffe/pic_147.jpg 3 +cartoon/giraffe/pic_144.jpg 3 +cartoon/giraffe/pic_146.jpg 3 +cartoon/giraffe/pic_149.jpg 3 +cartoon/giraffe/pic_148.jpg 3 +cartoon/giraffe/pic_343.jpg 3 +cartoon/giraffe/pic_346.jpg 3 +cartoon/giraffe/pic_352.jpg 3 +cartoon/giraffe/pic_355.jpg 3 +cartoon/giraffe/pic_354.jpg 3 +cartoon/giraffe/pic_351.jpg 3 +cartoon/giraffe/pic_350.jpg 3 +cartoon/giraffe/pic_353.jpg 3 +cartoon/giraffe/pic_349.jpg 3 +cartoon/giraffe/pic_359.jpg 3 +cartoon/giraffe/pic_360.jpg 3 +cartoon/giraffe/pic_361.jpg 3 +cartoon/giraffe/pic_358.jpg 3 +cartoon/giraffe/pic_356.jpg 3 +cartoon/giraffe/pic_374.jpg 3 +cartoon/giraffe/pic_372.jpg 3 +cartoon/giraffe/pic_371.jpg 3 +cartoon/giraffe/pic_174.jpg 3 +cartoon/giraffe/pic_172.jpg 3 +cartoon/giraffe/pic_173.jpg 3 +cartoon/giraffe/pic_177.jpg 3 +cartoon/giraffe/pic_175.jpg 3 +cartoon/giraffe/pic_176.jpg 3 +cartoon/giraffe/pic_178.jpg 3 +cartoon/giraffe/pic_179.jpg 3 +cartoon/giraffe/pic_180.jpg 3 +cartoon/giraffe/pic_181.jpg 3 +cartoon/giraffe/pic_182.jpg 3 +cartoon/giraffe/pic_185.jpg 3 +cartoon/giraffe/pic_183.jpg 3 +cartoon/giraffe/pic_186.jpg 3 +cartoon/giraffe/pic_187.jpg 3 +cartoon/giraffe/pic_188.jpg 3 +cartoon/giraffe/pic_189.jpg 3 +cartoon/giraffe/pic_190.jpg 3 +cartoon/giraffe/pic_192.jpg 3 +cartoon/giraffe/pic_262.jpg 3 +cartoon/giraffe/pic_265.jpg 3 +cartoon/giraffe/pic_266.jpg 3 +cartoon/giraffe/pic_264.jpg 3 +cartoon/giraffe/pic_267.jpg 3 +cartoon/giraffe/pic_268.jpg 3 +cartoon/giraffe/pic_269.jpg 3 +cartoon/giraffe/pic_270.jpg 3 +cartoon/giraffe/pic_272.jpg 3 +cartoon/giraffe/pic_271.jpg 3 +cartoon/giraffe/pic_275.jpg 3 +cartoon/giraffe/pic_274.jpg 3 +cartoon/giraffe/pic_273.jpg 3 +cartoon/giraffe/pic_276.jpg 3 +cartoon/giraffe/pic_279.jpg 3 +cartoon/giraffe/pic_277.jpg 3 +cartoon/giraffe/pic_278.jpg 3 +cartoon/giraffe/pic_280.jpg 3 +cartoon/giraffe/pic_063.jpg 3 +cartoon/giraffe/pic_068.jpg 3 +cartoon/giraffe/pic_080.jpg 3 +cartoon/giraffe/pic_082.jpg 3 +cartoon/giraffe/pic_079.jpg 3 +cartoon/giraffe/pic_077.jpg 3 +cartoon/giraffe/pic_078.jpg 3 +cartoon/giraffe/pic_074.jpg 3 +cartoon/giraffe/pic_075.jpg 3 +cartoon/giraffe/pic_073.jpg 3 +cartoon/giraffe/pic_072.jpg 3 +cartoon/giraffe/pic_071.jpg 3 +cartoon/giraffe/pic_069.jpg 3 +cartoon/giraffe/pic_083.jpg 3 +cartoon/giraffe/pic_084.jpg 3 +cartoon/giraffe/pic_076.jpg 3 +cartoon/giraffe/pic_089.jpg 3 +cartoon/giraffe/pic_088.jpg 3 +cartoon/giraffe/pic_194.jpg 3 +cartoon/giraffe/pic_193.jpg 3 +cartoon/giraffe/pic_195.jpg 3 +cartoon/giraffe/pic_196.jpg 3 +cartoon/giraffe/pic_197.jpg 3 +cartoon/giraffe/pic_198.jpg 3 +cartoon/giraffe/pic_199.jpg 3 +cartoon/giraffe/pic_200.jpg 3 +cartoon/giraffe/pic_201.jpg 3 +cartoon/giraffe/pic_202.jpg 3 +cartoon/giraffe/pic_203.jpg 3 +cartoon/giraffe/pic_204.jpg 3 +cartoon/giraffe/pic_205.jpg 3 +cartoon/giraffe/pic_206.jpg 3 +cartoon/giraffe/pic_209.jpg 3 +cartoon/giraffe/pic_208.jpg 3 +cartoon/giraffe/pic_210.jpg 3 +cartoon/giraffe/pic_212.jpg 3 +cartoon/giraffe/pic_211.jpg 3 +cartoon/giraffe/pic_216.jpg 3 +cartoon/giraffe/pic_102.jpg 3 +cartoon/giraffe/pic_105.jpg 3 +cartoon/giraffe/pic_121.jpg 3 +cartoon/giraffe/pic_124.jpg 3 +cartoon/giraffe/pic_122.jpg 3 +cartoon/giraffe/pic_119.jpg 3 +cartoon/giraffe/pic_118.jpg 3 +cartoon/giraffe/pic_117.jpg 3 +cartoon/giraffe/pic_115.jpg 3 +cartoon/giraffe/pic_116.jpg 3 +cartoon/giraffe/pic_114.jpg 3 +cartoon/giraffe/pic_112.jpg 3 +cartoon/giraffe/pic_111.jpg 3 +cartoon/giraffe/pic_123.jpg 3 +cartoon/giraffe/pic_113.jpg 3 +cartoon/giraffe/pic_120.jpg 3 +cartoon/giraffe/pic_127.jpg 3 +cartoon/giraffe/pic_126.jpg 3 +cartoon/giraffe/pic_125.jpg 3 +cartoon/giraffe/pic_129.jpg 3 +cartoon/giraffe/pic_128.jpg 3 +cartoon/giraffe/pic_001.jpg 3 +cartoon/giraffe/pic_002.jpg 3 +cartoon/giraffe/pic_003.jpg 3 +cartoon/giraffe/pic_004.jpg 3 +cartoon/giraffe/pic_215.jpg 3 +cartoon/giraffe/pic_214.jpg 3 +cartoon/giraffe/pic_213.jpg 3 +cartoon/giraffe/pic_218.jpg 3 +cartoon/giraffe/pic_219.jpg 3 +cartoon/giraffe/pic_217.jpg 3 +cartoon/giraffe/pic_220.jpg 3 +cartoon/giraffe/pic_221.jpg 3 +cartoon/giraffe/pic_222.jpg 3 +cartoon/giraffe/pic_224.jpg 3 +cartoon/giraffe/pic_225.jpg 3 +cartoon/giraffe/pic_226.jpg 3 +cartoon/giraffe/pic_227.jpg 3 +cartoon/giraffe/pic_228.jpg 3 +cartoon/giraffe/pic_229.jpg 3 +cartoon/giraffe/pic_230.jpg 3 +cartoon/giraffe/pic_231.jpg 3 +cartoon/giraffe/pic_232.jpg 3 +cartoon/giraffe/pic_344.jpg 3 +cartoon/giraffe/pic_345.jpg 3 +cartoon/giraffe/pic_342.jpg 3 +cartoon/giraffe/pic_334.jpg 3 +cartoon/giraffe/pic_335.jpg 3 +cartoon/giraffe/pic_327.jpg 3 +cartoon/giraffe/pic_330.jpg 3 +cartoon/giraffe/pic_333.jpg 3 +cartoon/giraffe/pic_328.jpg 3 +cartoon/giraffe/pic_331.jpg 3 +cartoon/giraffe/pic_326.jpg 3 +cartoon/giraffe/pic_324.jpg 3 +cartoon/giraffe/pic_323.jpg 3 +cartoon/giraffe/pic_347.jpg 3 +cartoon/giraffe/pic_341.jpg 3 +cartoon/giraffe/pic_336.jpg 3 +cartoon/giraffe/pic_339.jpg 3 +cartoon/giraffe/pic_337.jpg 3 +cartoon/giraffe/pic_304.jpg 3 +cartoon/giraffe/pic_302.jpg 3 +cartoon/giraffe/pic_297.jpg 3 +cartoon/giraffe/pic_295.jpg 3 +cartoon/giraffe/pic_299.jpg 3 +cartoon/giraffe/pic_316.jpg 3 +cartoon/giraffe/pic_312.jpg 3 +cartoon/giraffe/pic_318.jpg 3 +cartoon/giraffe/pic_319.jpg 3 +cartoon/giraffe/pic_308.jpg 3 +cartoon/giraffe/pic_310.jpg 3 +cartoon/giraffe/pic_309.jpg 3 +cartoon/giraffe/pic_301.jpg 3 +cartoon/giraffe/pic_311.jpg 3 +cartoon/giraffe/pic_322.jpg 3 +cartoon/giraffe/pic_321.jpg 3 +cartoon/giraffe/pic_300.jpg 3 +cartoon/giraffe/pic_317.jpg 3 +cartoon/giraffe/pic_340.jpg 3 +cartoon/giraffe/pic_242.jpg 3 +cartoon/giraffe/pic_241.jpg 3 +cartoon/giraffe/pic_243.jpg 3 +cartoon/giraffe/pic_244.jpg 3 +cartoon/giraffe/pic_245.jpg 3 +cartoon/giraffe/pic_246.jpg 3 +cartoon/giraffe/pic_247.jpg 3 +cartoon/giraffe/pic_249.jpg 3 +cartoon/giraffe/pic_248.jpg 3 +cartoon/giraffe/pic_251.jpg 3 +cartoon/giraffe/pic_252.jpg 3 +cartoon/giraffe/pic_253.jpg 3 +cartoon/giraffe/pic_254.jpg 3 +cartoon/giraffe/pic_256.jpg 3 +cartoon/giraffe/pic_257.jpg 3 +cartoon/giraffe/pic_259.jpg 3 +cartoon/giraffe/pic_260.jpg 3 +cartoon/giraffe/pic_261.jpg 3 +cartoon/guitar/pic_072.jpg 4 +cartoon/guitar/pic_003.jpg 4 +cartoon/guitar/pic_004.jpg 4 +cartoon/guitar/pic_005.jpg 4 +cartoon/guitar/pic_006.jpg 4 +cartoon/guitar/pic_007.jpg 4 +cartoon/guitar/pic_009.jpg 4 +cartoon/guitar/pic_010.jpg 4 +cartoon/guitar/pic_011.jpg 4 +cartoon/guitar/pic_012.jpg 4 +cartoon/guitar/pic_013.jpg 4 +cartoon/guitar/pic_016.jpg 4 +cartoon/guitar/pic_017.jpg 4 +cartoon/guitar/pic_020.jpg 4 +cartoon/guitar/pic_019.jpg 4 +cartoon/guitar/pic_022.jpg 4 +cartoon/guitar/pic_028.jpg 4 +cartoon/guitar/pic_025.jpg 4 +cartoon/guitar/pic_069.jpg 4 +cartoon/guitar/pic_067.jpg 4 +cartoon/guitar/pic_068.jpg 4 +cartoon/guitar/pic_063.jpg 4 +cartoon/guitar/pic_066.jpg 4 +cartoon/guitar/pic_064.jpg 4 +cartoon/guitar/pic_071.jpg 4 +cartoon/guitar/pic_070.jpg 4 +cartoon/guitar/pic_076.jpg 4 +cartoon/guitar/pic_074.jpg 4 +cartoon/guitar/pic_077.jpg 4 +cartoon/guitar/pic_075.jpg 4 +cartoon/guitar/pic_079.jpg 4 +cartoon/guitar/pic_078.jpg 4 +cartoon/guitar/pic_112.jpg 4 +cartoon/guitar/pic_135.jpg 4 +cartoon/guitar/pic_151.jpg 4 +cartoon/guitar/pic_133.jpg 4 +cartoon/guitar/pic_128.jpg 4 +cartoon/guitar/pic_122.jpg 4 +cartoon/guitar/pic_024.jpg 4 +cartoon/guitar/pic_023.jpg 4 +cartoon/guitar/pic_027.jpg 4 +cartoon/guitar/pic_034.jpg 4 +cartoon/guitar/pic_032.jpg 4 +cartoon/guitar/pic_031.jpg 4 +cartoon/guitar/pic_030.jpg 4 +cartoon/guitar/pic_029.jpg 4 +cartoon/guitar/pic_037.jpg 4 +cartoon/guitar/pic_036.jpg 4 +cartoon/guitar/pic_038.jpg 4 +cartoon/guitar/pic_040.jpg 4 +cartoon/guitar/pic_048.jpg 4 +cartoon/guitar/pic_045.jpg 4 +cartoon/guitar/pic_044.jpg 4 +cartoon/guitar/pic_043.jpg 4 +cartoon/guitar/pic_042.jpg 4 +cartoon/guitar/pic_021.jpg 4 +cartoon/guitar/pic_018.jpg 4 +cartoon/guitar/pic_039.jpg 4 +cartoon/guitar/pic_026.jpg 4 +cartoon/guitar/pic_104.jpg 4 +cartoon/guitar/pic_098.jpg 4 +cartoon/guitar/pic_146.jpg 4 +cartoon/guitar/pic_131.jpg 4 +cartoon/guitar/pic_106.jpg 4 +cartoon/guitar/pic_124.jpg 4 +cartoon/guitar/pic_137.jpg 4 +cartoon/guitar/pic_092.jpg 4 +cartoon/guitar/pic_096.jpg 4 +cartoon/guitar/pic_086.jpg 4 +cartoon/guitar/pic_145.jpg 4 +cartoon/guitar/pic_123.jpg 4 +cartoon/guitar/pic_111.jpg 4 +cartoon/guitar/pic_116.jpg 4 +cartoon/guitar/pic_150.jpg 4 +cartoon/guitar/pic_113.jpg 4 +cartoon/guitar/pic_107.jpg 4 +cartoon/guitar/pic_103.jpg 4 +cartoon/guitar/pic_097.jpg 4 +cartoon/guitar/pic_090.jpg 4 +cartoon/guitar/pic_088.jpg 4 +cartoon/guitar/pic_085.jpg 4 +cartoon/guitar/pic_083.jpg 4 +cartoon/guitar/pic_084.jpg 4 +cartoon/guitar/pic_082.jpg 4 +cartoon/guitar/pic_081.jpg 4 +cartoon/guitar/pic_080.jpg 4 +cartoon/guitar/pic_139.jpg 4 +cartoon/guitar/pic_140.jpg 4 +cartoon/guitar/pic_125.jpg 4 +cartoon/guitar/pic_117.jpg 4 +cartoon/guitar/pic_033.jpg 4 +cartoon/guitar/pic_035.jpg 4 +cartoon/guitar/pic_047.jpg 4 +cartoon/guitar/pic_046.jpg 4 +cartoon/guitar/pic_049.jpg 4 +cartoon/guitar/pic_052.jpg 4 +cartoon/guitar/pic_051.jpg 4 +cartoon/guitar/pic_053.jpg 4 +cartoon/guitar/pic_050.jpg 4 +cartoon/guitar/pic_054.jpg 4 +cartoon/guitar/pic_056.jpg 4 +cartoon/guitar/pic_055.jpg 4 +cartoon/guitar/pic_057.jpg 4 +cartoon/guitar/pic_060.jpg 4 +cartoon/guitar/pic_058.jpg 4 +cartoon/guitar/pic_059.jpg 4 +cartoon/guitar/pic_061.jpg 4 +cartoon/guitar/pic_065.jpg 4 +cartoon/guitar/pic_062.jpg 4 +cartoon/guitar/pic_073.jpg 4 +cartoon/guitar/pic_105.jpg 4 +cartoon/guitar/pic_136.jpg 4 +cartoon/guitar/pic_129.jpg 4 +cartoon/guitar/pic_110.jpg 4 +cartoon/guitar/pic_142.jpg 4 +cartoon/guitar/pic_089.jpg 4 +cartoon/guitar/pic_127.jpg 4 +cartoon/guitar/pic_148.jpg 4 +cartoon/guitar/pic_093.jpg 4 +cartoon/guitar/pic_100.jpg 4 +cartoon/guitar/pic_144.jpg 4 +cartoon/guitar/pic_149.jpg 4 +cartoon/guitar/pic_119.jpg 4 +cartoon/guitar/pic_121.jpg 4 +cartoon/guitar/pic_130.jpg 4 +cartoon/guitar/pic_094.jpg 4 +cartoon/guitar/pic_147.jpg 4 +cartoon/guitar/pic_099.jpg 4 +cartoon/guitar/pic_101.jpg 4 +cartoon/guitar/pic_132.jpg 4 +cartoon/guitar/pic_152.jpg 4 +cartoon/guitar/pic_134.jpg 4 +cartoon/guitar/pic_118.jpg 4 +cartoon/guitar/pic_001.jpg 4 +cartoon/guitar/pic_002.jpg 4 +cartoon/horse/pic_329.jpg 5 +cartoon/horse/pic_317.jpg 5 +cartoon/horse/pic_331.jpg 5 +cartoon/horse/pic_333.jpg 5 +cartoon/horse/pic_332.jpg 5 +cartoon/horse/pic_334.jpg 5 +cartoon/horse/pic_324.jpg 5 +cartoon/horse/pic_318.jpg 5 +cartoon/horse/pic_338.jpg 5 +cartoon/horse/pic_337.jpg 5 +cartoon/horse/pic_341.jpg 5 +cartoon/horse/pic_340.jpg 5 +cartoon/horse/pic_335.jpg 5 +cartoon/horse/pic_342.jpg 5 +cartoon/horse/pic_347.jpg 5 +cartoon/horse/pic_346.jpg 5 +cartoon/horse/pic_343.jpg 5 +cartoon/horse/pic_336.jpg 5 +cartoon/horse/pic_348.jpg 5 +cartoon/horse/pic_339.jpg 5 +cartoon/horse/pic_349.jpg 5 +cartoon/horse/pic_139.jpg 5 +cartoon/horse/pic_132.jpg 5 +cartoon/horse/pic_141.jpg 5 +cartoon/horse/pic_133.jpg 5 +cartoon/horse/pic_162.jpg 5 +cartoon/horse/pic_155.jpg 5 +cartoon/horse/pic_159.jpg 5 +cartoon/horse/pic_156.jpg 5 +cartoon/horse/pic_151.jpg 5 +cartoon/horse/pic_149.jpg 5 +cartoon/horse/pic_147.jpg 5 +cartoon/horse/pic_161.jpg 5 +cartoon/horse/pic_153.jpg 5 +cartoon/horse/pic_158.jpg 5 +cartoon/horse/pic_157.jpg 5 +cartoon/horse/pic_010.jpg 5 +cartoon/horse/pic_011.jpg 5 +cartoon/horse/pic_012.jpg 5 +cartoon/horse/pic_013.jpg 5 +cartoon/horse/pic_014.jpg 5 +cartoon/horse/pic_015.jpg 5 +cartoon/horse/pic_016.jpg 5 +cartoon/horse/pic_017.jpg 5 +cartoon/horse/pic_018.jpg 5 +cartoon/horse/pic_019.jpg 5 +cartoon/horse/pic_020.jpg 5 +cartoon/horse/pic_022.jpg 5 +cartoon/horse/pic_021.jpg 5 +cartoon/horse/pic_023.jpg 5 +cartoon/horse/pic_024.jpg 5 +cartoon/horse/pic_025.jpg 5 +cartoon/horse/pic_026.jpg 5 +cartoon/horse/pic_027.jpg 5 +cartoon/horse/pic_028.jpg 5 +cartoon/horse/pic_029.jpg 5 +cartoon/horse/pic_030.jpg 5 +cartoon/horse/pic_267.jpg 5 +cartoon/horse/pic_266.jpg 5 +cartoon/horse/pic_271.jpg 5 +cartoon/horse/pic_270.jpg 5 +cartoon/horse/pic_261.jpg 5 +cartoon/horse/pic_273.jpg 5 +cartoon/horse/pic_272.jpg 5 +cartoon/horse/pic_274.jpg 5 +cartoon/horse/pic_275.jpg 5 +cartoon/horse/pic_277.jpg 5 +cartoon/horse/pic_276.jpg 5 +cartoon/horse/pic_278.jpg 5 +cartoon/horse/pic_279.jpg 5 +cartoon/horse/pic_283.jpg 5 +cartoon/horse/pic_284.jpg 5 +cartoon/horse/pic_287.jpg 5 +cartoon/horse/pic_286.jpg 5 +cartoon/horse/pic_288.jpg 5 +cartoon/horse/pic_289.jpg 5 +cartoon/horse/pic_062.jpg 5 +cartoon/horse/pic_067.jpg 5 +cartoon/horse/pic_064.jpg 5 +cartoon/horse/pic_059.jpg 5 +cartoon/horse/pic_057.jpg 5 +cartoon/horse/pic_056.jpg 5 +cartoon/horse/pic_031.jpg 5 +cartoon/horse/pic_032.jpg 5 +cartoon/horse/pic_033.jpg 5 +cartoon/horse/pic_307.jpg 5 +cartoon/horse/pic_309.jpg 5 +cartoon/horse/pic_299.jpg 5 +cartoon/horse/pic_311.jpg 5 +cartoon/horse/pic_312.jpg 5 +cartoon/horse/pic_313.jpg 5 +cartoon/horse/pic_314.jpg 5 +cartoon/horse/pic_315.jpg 5 +cartoon/horse/pic_316.jpg 5 +cartoon/horse/pic_319.jpg 5 +cartoon/horse/pic_310.jpg 5 +cartoon/horse/pic_323.jpg 5 +cartoon/horse/pic_322.jpg 5 +cartoon/horse/pic_320.jpg 5 +cartoon/horse/pic_328.jpg 5 +cartoon/horse/pic_327.jpg 5 +cartoon/horse/pic_330.jpg 5 +cartoon/horse/pic_089.jpg 5 +cartoon/horse/pic_118.jpg 5 +cartoon/horse/pic_114.jpg 5 +cartoon/horse/pic_113.jpg 5 +cartoon/horse/pic_112.jpg 5 +cartoon/horse/pic_103.jpg 5 +cartoon/horse/pic_105.jpg 5 +cartoon/horse/pic_104.jpg 5 +cartoon/horse/pic_100.jpg 5 +cartoon/horse/pic_101.jpg 5 +cartoon/horse/pic_119.jpg 5 +cartoon/horse/pic_115.jpg 5 +cartoon/horse/pic_110.jpg 5 +cartoon/horse/pic_126.jpg 5 +cartoon/horse/pic_106.jpg 5 +cartoon/horse/pic_120.jpg 5 +cartoon/horse/pic_054.jpg 5 +cartoon/horse/pic_055.jpg 5 +cartoon/horse/pic_053.jpg 5 +cartoon/horse/pic_052.jpg 5 +cartoon/horse/pic_051.jpg 5 +cartoon/horse/pic_050.jpg 5 +cartoon/horse/pic_049.jpg 5 +cartoon/horse/pic_076.jpg 5 +cartoon/horse/pic_066.jpg 5 +cartoon/horse/pic_081.jpg 5 +cartoon/horse/pic_079.jpg 5 +cartoon/horse/pic_060.jpg 5 +cartoon/horse/pic_058.jpg 5 +cartoon/horse/pic_069.jpg 5 +cartoon/horse/pic_074.jpg 5 +cartoon/horse/pic_065.jpg 5 +cartoon/horse/pic_075.jpg 5 +cartoon/horse/pic_078.jpg 5 +cartoon/horse/pic_070.jpg 5 +cartoon/horse/pic_072.jpg 5 +cartoon/horse/pic_291.jpg 5 +cartoon/horse/pic_282.jpg 5 +cartoon/horse/pic_293.jpg 5 +cartoon/horse/pic_294.jpg 5 +cartoon/horse/pic_295.jpg 5 +cartoon/horse/pic_297.jpg 5 +cartoon/horse/pic_268.jpg 5 +cartoon/horse/pic_296.jpg 5 +cartoon/horse/pic_298.jpg 5 +cartoon/horse/pic_300.jpg 5 +cartoon/horse/pic_302.jpg 5 +cartoon/horse/pic_280.jpg 5 +cartoon/horse/pic_304.jpg 5 +cartoon/horse/pic_303.jpg 5 +cartoon/horse/pic_305.jpg 5 +cartoon/horse/pic_308.jpg 5 +cartoon/horse/pic_183.jpg 5 +cartoon/horse/pic_184.jpg 5 +cartoon/horse/pic_185.jpg 5 +cartoon/horse/pic_188.jpg 5 +cartoon/horse/pic_186.jpg 5 +cartoon/horse/pic_187.jpg 5 +cartoon/horse/pic_189.jpg 5 +cartoon/horse/pic_178.jpg 5 +cartoon/horse/pic_191.jpg 5 +cartoon/horse/pic_193.jpg 5 +cartoon/horse/pic_190.jpg 5 +cartoon/horse/pic_200.jpg 5 +cartoon/horse/pic_196.jpg 5 +cartoon/horse/pic_195.jpg 5 +cartoon/horse/pic_201.jpg 5 +cartoon/horse/pic_198.jpg 5 +cartoon/horse/pic_204.jpg 5 +cartoon/horse/pic_245.jpg 5 +cartoon/horse/pic_250.jpg 5 +cartoon/horse/pic_252.jpg 5 +cartoon/horse/pic_255.jpg 5 +cartoon/horse/pic_254.jpg 5 +cartoon/horse/pic_235.jpg 5 +cartoon/horse/pic_256.jpg 5 +cartoon/horse/pic_258.jpg 5 +cartoon/horse/pic_257.jpg 5 +cartoon/horse/pic_253.jpg 5 +cartoon/horse/pic_240.jpg 5 +cartoon/horse/pic_243.jpg 5 +cartoon/horse/pic_260.jpg 5 +cartoon/horse/pic_246.jpg 5 +cartoon/horse/pic_262.jpg 5 +cartoon/horse/pic_251.jpg 5 +cartoon/horse/pic_264.jpg 5 +cartoon/horse/pic_263.jpg 5 +cartoon/horse/pic_265.jpg 5 +cartoon/horse/pic_259.jpg 5 +cartoon/horse/pic_269.jpg 5 +cartoon/horse/pic_001.jpg 5 +cartoon/horse/pic_002.jpg 5 +cartoon/horse/pic_003.jpg 5 +cartoon/horse/pic_004.jpg 5 +cartoon/horse/pic_005.jpg 5 +cartoon/horse/pic_006.jpg 5 +cartoon/horse/pic_007.jpg 5 +cartoon/horse/pic_008.jpg 5 +cartoon/horse/pic_009.jpg 5 +cartoon/horse/pic_116.jpg 5 +cartoon/horse/pic_108.jpg 5 +cartoon/horse/pic_111.jpg 5 +cartoon/horse/pic_128.jpg 5 +cartoon/horse/pic_124.jpg 5 +cartoon/horse/pic_130.jpg 5 +cartoon/horse/pic_131.jpg 5 +cartoon/horse/pic_129.jpg 5 +cartoon/horse/pic_125.jpg 5 +cartoon/horse/pic_121.jpg 5 +cartoon/horse/pic_127.jpg 5 +cartoon/horse/pic_123.jpg 5 +cartoon/horse/pic_143.jpg 5 +cartoon/horse/pic_135.jpg 5 +cartoon/horse/pic_134.jpg 5 +cartoon/horse/pic_140.jpg 5 +cartoon/horse/pic_145.jpg 5 +cartoon/horse/pic_146.jpg 5 +cartoon/horse/pic_142.jpg 5 +cartoon/horse/pic_137.jpg 5 +cartoon/horse/pic_350.jpg 5 +cartoon/horse/pic_351.jpg 5 +cartoon/horse/pic_352.jpg 5 +cartoon/horse/pic_353.jpg 5 +cartoon/horse/pic_354.jpg 5 +cartoon/horse/pic_355.jpg 5 +cartoon/horse/pic_345.jpg 5 +cartoon/horse/pic_357.jpg 5 +cartoon/horse/pic_359.jpg 5 +cartoon/horse/pic_358.jpg 5 +cartoon/horse/pic_361.jpg 5 +cartoon/horse/pic_362.jpg 5 +cartoon/horse/pic_364.jpg 5 +cartoon/horse/pic_356.jpg 5 +cartoon/horse/pic_363.jpg 5 +cartoon/horse/pic_160.jpg 5 +cartoon/horse/pic_173.jpg 5 +cartoon/horse/pic_172.jpg 5 +cartoon/horse/pic_169.jpg 5 +cartoon/horse/pic_167.jpg 5 +cartoon/horse/pic_166.jpg 5 +cartoon/horse/pic_164.jpg 5 +cartoon/horse/pic_163.jpg 5 +cartoon/horse/pic_152.jpg 5 +cartoon/horse/pic_174.jpg 5 +cartoon/horse/pic_171.jpg 5 +cartoon/horse/pic_177.jpg 5 +cartoon/horse/pic_176.jpg 5 +cartoon/horse/pic_181.jpg 5 +cartoon/horse/pic_180.jpg 5 +cartoon/horse/pic_179.jpg 5 +cartoon/horse/pic_084.jpg 5 +cartoon/horse/pic_083.jpg 5 +cartoon/horse/pic_071.jpg 5 +cartoon/horse/pic_096.jpg 5 +cartoon/horse/pic_094.jpg 5 +cartoon/horse/pic_098.jpg 5 +cartoon/horse/pic_095.jpg 5 +cartoon/horse/pic_093.jpg 5 +cartoon/horse/pic_092.jpg 5 +cartoon/horse/pic_091.jpg 5 +cartoon/horse/pic_090.jpg 5 +cartoon/horse/pic_088.jpg 5 +cartoon/horse/pic_086.jpg 5 +cartoon/horse/pic_097.jpg 5 +cartoon/horse/pic_087.jpg 5 +cartoon/horse/pic_203.jpg 5 +cartoon/horse/pic_205.jpg 5 +cartoon/horse/pic_209.jpg 5 +cartoon/horse/pic_212.jpg 5 +cartoon/horse/pic_213.jpg 5 +cartoon/horse/pic_192.jpg 5 +cartoon/horse/pic_211.jpg 5 +cartoon/horse/pic_214.jpg 5 +cartoon/horse/pic_218.jpg 5 +cartoon/horse/pic_215.jpg 5 +cartoon/horse/pic_217.jpg 5 +cartoon/horse/pic_220.jpg 5 +cartoon/horse/pic_219.jpg 5 +cartoon/horse/pic_221.jpg 5 +cartoon/horse/pic_223.jpg 5 +cartoon/horse/pic_224.jpg 5 +cartoon/horse/pic_208.jpg 5 +cartoon/horse/pic_035.jpg 5 +cartoon/horse/pic_034.jpg 5 +cartoon/horse/pic_037.jpg 5 +cartoon/horse/pic_036.jpg 5 +cartoon/horse/pic_044.jpg 5 +cartoon/horse/pic_047.jpg 5 +cartoon/horse/pic_045.jpg 5 +cartoon/horse/pic_043.jpg 5 +cartoon/horse/pic_042.jpg 5 +cartoon/horse/pic_040.jpg 5 +cartoon/horse/pic_041.jpg 5 +cartoon/horse/pic_038.jpg 5 +cartoon/horse/pic_039.jpg 5 +cartoon/horse/pic_048.jpg 5 +cartoon/horse/pic_046.jpg 5 +cartoon/horse/pic_061.jpg 5 +cartoon/horse/pic_073.jpg 5 +cartoon/horse/pic_077.jpg 5 +cartoon/horse/pic_080.jpg 5 +cartoon/horse/pic_082.jpg 5 +cartoon/horse/pic_225.jpg 5 +cartoon/horse/pic_228.jpg 5 +cartoon/horse/pic_207.jpg 5 +cartoon/horse/pic_227.jpg 5 +cartoon/horse/pic_226.jpg 5 +cartoon/horse/pic_231.jpg 5 +cartoon/horse/pic_232.jpg 5 +cartoon/horse/pic_234.jpg 5 +cartoon/horse/pic_236.jpg 5 +cartoon/horse/pic_237.jpg 5 +cartoon/horse/pic_239.jpg 5 +cartoon/horse/pic_238.jpg 5 +cartoon/horse/pic_229.jpg 5 +cartoon/horse/pic_241.jpg 5 +cartoon/horse/pic_242.jpg 5 +cartoon/horse/pic_244.jpg 5 +cartoon/horse/pic_233.jpg 5 +cartoon/horse/pic_249.jpg 5 +cartoon/horse/pic_248.jpg 5 +cartoon/horse/pic_247.jpg 5 +cartoon/house/pic_103.jpg 6 +cartoon/house/pic_091.jpg 6 +cartoon/house/pic_089.jpg 6 +cartoon/house/pic_092.jpg 6 +cartoon/house/pic_093.jpg 6 +cartoon/house/pic_107.jpg 6 +cartoon/house/pic_104.jpg 6 +cartoon/house/pic_114.jpg 6 +cartoon/house/pic_112.jpg 6 +cartoon/house/pic_109.jpg 6 +cartoon/house/pic_108.jpg 6 +cartoon/house/pic_102.jpg 6 +cartoon/house/pic_099.jpg 6 +cartoon/house/pic_098.jpg 6 +cartoon/house/pic_097.jpg 6 +cartoon/house/pic_111.jpg 6 +cartoon/house/pic_320.jpg 6 +cartoon/house/pic_321.jpg 6 +cartoon/house/pic_315.jpg 6 +cartoon/house/pic_322.jpg 6 +cartoon/house/pic_323.jpg 6 +cartoon/house/pic_311.jpg 6 +cartoon/house/pic_324.jpg 6 +cartoon/house/pic_327.jpg 6 +cartoon/house/pic_312.jpg 6 +cartoon/house/pic_314.jpg 6 +cartoon/house/pic_328.jpg 6 +cartoon/house/pic_069.jpg 6 +cartoon/house/pic_079.jpg 6 +cartoon/house/pic_071.jpg 6 +cartoon/house/pic_072.jpg 6 +cartoon/house/pic_074.jpg 6 +cartoon/house/pic_077.jpg 6 +cartoon/house/pic_081.jpg 6 +cartoon/house/pic_088.jpg 6 +cartoon/house/pic_082.jpg 6 +cartoon/house/pic_080.jpg 6 +cartoon/house/pic_090.jpg 6 +cartoon/house/pic_100.jpg 6 +cartoon/house/pic_084.jpg 6 +cartoon/house/pic_085.jpg 6 +cartoon/house/pic_083.jpg 6 +cartoon/house/pic_087.jpg 6 +cartoon/house/pic_094.jpg 6 +cartoon/house/pic_157.jpg 6 +cartoon/house/pic_169.jpg 6 +cartoon/house/pic_172.jpg 6 +cartoon/house/pic_173.jpg 6 +cartoon/house/pic_171.jpg 6 +cartoon/house/pic_176.jpg 6 +cartoon/house/pic_180.jpg 6 +cartoon/house/pic_182.jpg 6 +cartoon/house/pic_185.jpg 6 +cartoon/house/pic_184.jpg 6 +cartoon/house/pic_187.jpg 6 +cartoon/house/pic_188.jpg 6 +cartoon/house/pic_189.jpg 6 +cartoon/house/pic_191.jpg 6 +cartoon/house/pic_174.jpg 6 +cartoon/house/pic_179.jpg 6 +cartoon/house/pic_237.jpg 6 +cartoon/house/pic_258.jpg 6 +cartoon/house/pic_260.jpg 6 +cartoon/house/pic_242.jpg 6 +cartoon/house/pic_262.jpg 6 +cartoon/house/pic_263.jpg 6 +cartoon/house/pic_249.jpg 6 +cartoon/house/pic_253.jpg 6 +cartoon/house/pic_257.jpg 6 +cartoon/house/pic_265.jpg 6 +cartoon/house/pic_267.jpg 6 +cartoon/house/pic_268.jpg 6 +cartoon/house/pic_269.jpg 6 +cartoon/house/pic_272.jpg 6 +cartoon/house/pic_264.jpg 6 +cartoon/house/pic_274.jpg 6 +cartoon/house/pic_270.jpg 6 +cartoon/house/pic_177.jpg 6 +cartoon/house/pic_192.jpg 6 +cartoon/house/pic_193.jpg 6 +cartoon/house/pic_178.jpg 6 +cartoon/house/pic_181.jpg 6 +cartoon/house/pic_194.jpg 6 +cartoon/house/pic_196.jpg 6 +cartoon/house/pic_197.jpg 6 +cartoon/house/pic_198.jpg 6 +cartoon/house/pic_199.jpg 6 +cartoon/house/pic_200.jpg 6 +cartoon/house/pic_201.jpg 6 +cartoon/house/pic_202.jpg 6 +cartoon/house/pic_203.jpg 6 +cartoon/house/pic_205.jpg 6 +cartoon/house/pic_195.jpg 6 +cartoon/house/pic_207.jpg 6 +cartoon/house/pic_206.jpg 6 +cartoon/house/pic_204.jpg 6 +cartoon/house/pic_209.jpg 6 +cartoon/house/pic_234.jpg 6 +cartoon/house/pic_239.jpg 6 +cartoon/house/pic_241.jpg 6 +cartoon/house/pic_240.jpg 6 +cartoon/house/pic_224.jpg 6 +cartoon/house/pic_243.jpg 6 +cartoon/house/pic_246.jpg 6 +cartoon/house/pic_245.jpg 6 +cartoon/house/pic_244.jpg 6 +cartoon/house/pic_250.jpg 6 +cartoon/house/pic_230.jpg 6 +cartoon/house/pic_238.jpg 6 +cartoon/house/pic_252.jpg 6 +cartoon/house/pic_254.jpg 6 +cartoon/house/pic_255.jpg 6 +cartoon/house/pic_256.jpg 6 +cartoon/house/pic_008.jpg 6 +cartoon/house/pic_009.jpg 6 +cartoon/house/pic_010.jpg 6 +cartoon/house/pic_011.jpg 6 +cartoon/house/pic_012.jpg 6 +cartoon/house/pic_013.jpg 6 +cartoon/house/pic_014.jpg 6 +cartoon/house/pic_016.jpg 6 +cartoon/house/pic_017.jpg 6 +cartoon/house/pic_020.jpg 6 +cartoon/house/pic_022.jpg 6 +cartoon/house/pic_026.jpg 6 +cartoon/house/pic_024.jpg 6 +cartoon/house/pic_027.jpg 6 +cartoon/house/pic_028.jpg 6 +cartoon/house/pic_032.jpg 6 +cartoon/house/pic_029.jpg 6 +cartoon/house/pic_001.jpg 6 +cartoon/house/pic_002.jpg 6 +cartoon/house/pic_003.jpg 6 +cartoon/house/pic_004.jpg 6 +cartoon/house/pic_005.jpg 6 +cartoon/house/pic_006.jpg 6 +cartoon/house/pic_007.jpg 6 +cartoon/house/pic_158.jpg 6 +cartoon/house/pic_160.jpg 6 +cartoon/house/pic_161.jpg 6 +cartoon/house/pic_162.jpg 6 +cartoon/house/pic_151.jpg 6 +cartoon/house/pic_164.jpg 6 +cartoon/house/pic_165.jpg 6 +cartoon/house/pic_156.jpg 6 +cartoon/house/pic_166.jpg 6 +cartoon/house/pic_167.jpg 6 +cartoon/house/pic_168.jpg 6 +cartoon/house/pic_163.jpg 6 +cartoon/house/pic_318.jpg 6 +cartoon/house/pic_331.jpg 6 +cartoon/house/pic_333.jpg 6 +cartoon/house/pic_334.jpg 6 +cartoon/house/pic_337.jpg 6 +cartoon/house/pic_335.jpg 6 +cartoon/house/pic_338.jpg 6 +cartoon/house/pic_341.jpg 6 +cartoon/house/pic_343.jpg 6 +cartoon/house/pic_344.jpg 6 +cartoon/house/pic_330.jpg 6 +cartoon/house/pic_346.jpg 6 +cartoon/house/pic_348.jpg 6 +cartoon/house/pic_340.jpg 6 +cartoon/house/pic_349.jpg 6 +cartoon/house/pic_347.jpg 6 +cartoon/house/pic_336.jpg 6 +cartoon/house/pic_355.jpg 6 +cartoon/house/pic_356.jpg 6 +cartoon/house/pic_357.jpg 6 +cartoon/house/pic_358.jpg 6 +cartoon/house/pic_360.jpg 6 +cartoon/house/pic_345.jpg 6 +cartoon/house/pic_354.jpg 6 +cartoon/house/pic_353.jpg 6 +cartoon/house/pic_359.jpg 6 +cartoon/house/pic_212.jpg 6 +cartoon/house/pic_211.jpg 6 +cartoon/house/pic_221.jpg 6 +cartoon/house/pic_219.jpg 6 +cartoon/house/pic_218.jpg 6 +cartoon/house/pic_215.jpg 6 +cartoon/house/pic_217.jpg 6 +cartoon/house/pic_220.jpg 6 +cartoon/house/pic_222.jpg 6 +cartoon/house/pic_223.jpg 6 +cartoon/house/pic_216.jpg 6 +cartoon/house/pic_208.jpg 6 +cartoon/house/pic_225.jpg 6 +cartoon/house/pic_226.jpg 6 +cartoon/house/pic_214.jpg 6 +cartoon/house/pic_231.jpg 6 +cartoon/house/pic_233.jpg 6 +cartoon/house/pic_228.jpg 6 +cartoon/house/pic_235.jpg 6 +cartoon/house/pic_273.jpg 6 +cartoon/house/pic_279.jpg 6 +cartoon/house/pic_278.jpg 6 +cartoon/house/pic_283.jpg 6 +cartoon/house/pic_280.jpg 6 +cartoon/house/pic_266.jpg 6 +cartoon/house/pic_281.jpg 6 +cartoon/house/pic_286.jpg 6 +cartoon/house/pic_276.jpg 6 +cartoon/house/pic_277.jpg 6 +cartoon/house/pic_288.jpg 6 +cartoon/house/pic_289.jpg 6 +cartoon/house/pic_282.jpg 6 +cartoon/house/pic_290.jpg 6 +cartoon/house/pic_292.jpg 6 +cartoon/house/pic_285.jpg 6 +cartoon/house/pic_295.jpg 6 +cartoon/house/pic_047.jpg 6 +cartoon/house/pic_049.jpg 6 +cartoon/house/pic_048.jpg 6 +cartoon/house/pic_050.jpg 6 +cartoon/house/pic_053.jpg 6 +cartoon/house/pic_056.jpg 6 +cartoon/house/pic_054.jpg 6 +cartoon/house/pic_059.jpg 6 +cartoon/house/pic_057.jpg 6 +cartoon/house/pic_067.jpg 6 +cartoon/house/pic_062.jpg 6 +cartoon/house/pic_060.jpg 6 +cartoon/house/pic_063.jpg 6 +cartoon/house/pic_066.jpg 6 +cartoon/house/pic_064.jpg 6 +cartoon/house/pic_065.jpg 6 +cartoon/house/pic_284.jpg 6 +cartoon/house/pic_297.jpg 6 +cartoon/house/pic_296.jpg 6 +cartoon/house/pic_298.jpg 6 +cartoon/house/pic_301.jpg 6 +cartoon/house/pic_302.jpg 6 +cartoon/house/pic_304.jpg 6 +cartoon/house/pic_305.jpg 6 +cartoon/house/pic_306.jpg 6 +cartoon/house/pic_291.jpg 6 +cartoon/house/pic_309.jpg 6 +cartoon/house/pic_308.jpg 6 +cartoon/house/pic_310.jpg 6 +cartoon/house/pic_299.jpg 6 +cartoon/house/pic_300.jpg 6 +cartoon/house/pic_303.jpg 6 +cartoon/house/pic_316.jpg 6 +cartoon/house/pic_317.jpg 6 +cartoon/house/pic_319.jpg 6 +cartoon/house/pic_039.jpg 6 +cartoon/house/pic_030.jpg 6 +cartoon/house/pic_034.jpg 6 +cartoon/house/pic_031.jpg 6 +cartoon/house/pic_038.jpg 6 +cartoon/house/pic_025.jpg 6 +cartoon/house/pic_051.jpg 6 +cartoon/house/pic_036.jpg 6 +cartoon/house/pic_041.jpg 6 +cartoon/house/pic_023.jpg 6 +cartoon/house/pic_046.jpg 6 +cartoon/house/pic_052.jpg 6 +cartoon/house/pic_040.jpg 6 +cartoon/house/pic_045.jpg 6 +cartoon/house/pic_044.jpg 6 +cartoon/house/pic_043.jpg 6 +cartoon/house/pic_042.jpg 6 +cartoon/house/pic_138.jpg 6 +cartoon/house/pic_140.jpg 6 +cartoon/house/pic_130.jpg 6 +cartoon/house/pic_143.jpg 6 +cartoon/house/pic_145.jpg 6 +cartoon/house/pic_146.jpg 6 +cartoon/house/pic_148.jpg 6 +cartoon/house/pic_147.jpg 6 +cartoon/house/pic_149.jpg 6 +cartoon/house/pic_152.jpg 6 +cartoon/house/pic_139.jpg 6 +cartoon/house/pic_153.jpg 6 +cartoon/house/pic_113.jpg 6 +cartoon/house/pic_116.jpg 6 +cartoon/house/pic_110.jpg 6 +cartoon/house/pic_122.jpg 6 +cartoon/house/pic_121.jpg 6 +cartoon/house/pic_120.jpg 6 +cartoon/house/pic_119.jpg 6 +cartoon/house/pic_118.jpg 6 +cartoon/house/pic_126.jpg 6 +cartoon/house/pic_123.jpg 6 +cartoon/house/pic_131.jpg 6 +cartoon/house/pic_132.jpg 6 +cartoon/house/pic_134.jpg 6 +cartoon/person/pic_308.jpg 7 +cartoon/person/pic_307.jpg 7 +cartoon/person/pic_306.jpg 7 +cartoon/person/pic_313.jpg 7 +cartoon/person/pic_323.jpg 7 +cartoon/person/pic_319.jpg 7 +cartoon/person/pic_320.jpg 7 +cartoon/person/pic_321.jpg 7 +cartoon/person/pic_318.jpg 7 +cartoon/person/pic_317.jpg 7 +cartoon/person/pic_316.jpg 7 +cartoon/person/pic_324.jpg 7 +cartoon/person/pic_334.jpg 7 +cartoon/person/pic_331.jpg 7 +cartoon/person/pic_332.jpg 7 +cartoon/person/pic_333.jpg 7 +cartoon/person/pic_144.jpg 7 +cartoon/person/pic_145.jpg 7 +cartoon/person/pic_143.jpg 7 +cartoon/person/pic_138.jpg 7 +cartoon/person/pic_154.jpg 7 +cartoon/person/pic_151.jpg 7 +cartoon/person/pic_152.jpg 7 +cartoon/person/pic_148.jpg 7 +cartoon/person/pic_149.jpg 7 +cartoon/person/pic_155.jpg 7 +cartoon/person/pic_157.jpg 7 +cartoon/person/pic_159.jpg 7 +cartoon/person/pic_176.jpg 7 +cartoon/person/pic_171.jpg 7 +cartoon/person/pic_168.jpg 7 +cartoon/person/pic_169.jpg 7 +cartoon/person/pic_167.jpg 7 +cartoon/person/pic_056.jpg 7 +cartoon/person/pic_071.jpg 7 +cartoon/person/pic_070.jpg 7 +cartoon/person/pic_069.jpg 7 +cartoon/person/pic_073.jpg 7 +cartoon/person/pic_075.jpg 7 +cartoon/person/pic_076.jpg 7 +cartoon/person/pic_068.jpg 7 +cartoon/person/pic_074.jpg 7 +cartoon/person/pic_072.jpg 7 +cartoon/person/pic_077.jpg 7 +cartoon/person/pic_094.jpg 7 +cartoon/person/pic_123.jpg 7 +cartoon/person/pic_110.jpg 7 +cartoon/person/pic_109.jpg 7 +cartoon/person/pic_100.jpg 7 +cartoon/person/pic_095.jpg 7 +cartoon/person/pic_087.jpg 7 +cartoon/person/pic_089.jpg 7 +cartoon/person/pic_365.jpg 7 +cartoon/person/pic_373.jpg 7 +cartoon/person/pic_381.jpg 7 +cartoon/person/pic_379.jpg 7 +cartoon/person/pic_370.jpg 7 +cartoon/person/pic_374.jpg 7 +cartoon/person/pic_377.jpg 7 +cartoon/person/pic_380.jpg 7 +cartoon/person/pic_393.jpg 7 +cartoon/person/pic_392.jpg 7 +cartoon/person/pic_391.jpg 7 +cartoon/person/pic_389.jpg 7 +cartoon/person/pic_390.jpg 7 +cartoon/person/pic_387.jpg 7 +cartoon/person/pic_386.jpg 7 +cartoon/person/pic_385.jpg 7 +cartoon/person/pic_384.jpg 7 +cartoon/person/pic_383.jpg 7 +cartoon/person/pic_382.jpg 7 +cartoon/person/pic_001.jpg 7 +cartoon/person/pic_002.jpg 7 +cartoon/person/pic_003.jpg 7 +cartoon/person/pic_004.jpg 7 +cartoon/person/pic_085.jpg 7 +cartoon/person/pic_084.jpg 7 +cartoon/person/pic_083.jpg 7 +cartoon/person/pic_082.jpg 7 +cartoon/person/pic_081.jpg 7 +cartoon/person/pic_079.jpg 7 +cartoon/person/pic_078.jpg 7 +cartoon/person/pic_121.jpg 7 +cartoon/person/pic_117.jpg 7 +cartoon/person/pic_120.jpg 7 +cartoon/person/pic_105.jpg 7 +cartoon/person/pic_027.jpg 7 +cartoon/person/pic_025.jpg 7 +cartoon/person/pic_026.jpg 7 +cartoon/person/pic_022.jpg 7 +cartoon/person/pic_019.jpg 7 +cartoon/person/pic_030.jpg 7 +cartoon/person/pic_037.jpg 7 +cartoon/person/pic_036.jpg 7 +cartoon/person/pic_035.jpg 7 +cartoon/person/pic_032.jpg 7 +cartoon/person/pic_033.jpg 7 +cartoon/person/pic_031.jpg 7 +cartoon/person/pic_034.jpg 7 +cartoon/person/pic_038.jpg 7 +cartoon/person/pic_039.jpg 7 +cartoon/person/pic_040.jpg 7 +cartoon/person/pic_042.jpg 7 +cartoon/person/pic_043.jpg 7 +cartoon/person/pic_041.jpg 7 +cartoon/person/pic_049.jpg 7 +cartoon/person/pic_048.jpg 7 +cartoon/person/pic_415.jpg 7 +cartoon/person/pic_427.jpg 7 +cartoon/person/pic_429.jpg 7 +cartoon/person/pic_420.jpg 7 +cartoon/person/pic_423.jpg 7 +cartoon/person/pic_438.jpg 7 +cartoon/person/pic_434.jpg 7 +cartoon/person/pic_436.jpg 7 +cartoon/person/pic_432.jpg 7 +cartoon/person/pic_433.jpg 7 +cartoon/person/pic_431.jpg 7 +cartoon/person/pic_430.jpg 7 +cartoon/person/pic_439.jpg 7 +cartoon/person/pic_435.jpg 7 +cartoon/person/pic_445.jpg 7 +cartoon/person/pic_444.jpg 7 +cartoon/person/pic_441.jpg 7 +cartoon/person/pic_442.jpg 7 +cartoon/person/pic_443.jpg 7 +cartoon/person/pic_440.jpg 7 +cartoon/person/pic_005.jpg 7 +cartoon/person/pic_007.jpg 7 +cartoon/person/pic_008.jpg 7 +cartoon/person/pic_009.jpg 7 +cartoon/person/pic_010.jpg 7 +cartoon/person/pic_011.jpg 7 +cartoon/person/pic_012.jpg 7 +cartoon/person/pic_013.jpg 7 +cartoon/person/pic_014.jpg 7 +cartoon/person/pic_015.jpg 7 +cartoon/person/pic_021.jpg 7 +cartoon/person/pic_024.jpg 7 +cartoon/person/pic_023.jpg 7 +cartoon/person/pic_020.jpg 7 +cartoon/person/pic_018.jpg 7 +cartoon/person/pic_016.jpg 7 +cartoon/person/pic_017.jpg 7 +cartoon/person/pic_029.jpg 7 +cartoon/person/pic_028.jpg 7 +cartoon/person/pic_165.jpg 7 +cartoon/person/pic_164.jpg 7 +cartoon/person/pic_162.jpg 7 +cartoon/person/pic_158.jpg 7 +cartoon/person/pic_160.jpg 7 +cartoon/person/pic_172.jpg 7 +cartoon/person/pic_173.jpg 7 +cartoon/person/pic_170.jpg 7 +cartoon/person/pic_174.jpg 7 +cartoon/person/pic_161.jpg 7 +cartoon/person/pic_163.jpg 7 +cartoon/person/pic_175.jpg 7 +cartoon/person/pic_177.jpg 7 +cartoon/person/pic_180.jpg 7 +cartoon/person/pic_179.jpg 7 +cartoon/person/pic_181.jpg 7 +cartoon/person/pic_184.jpg 7 +cartoon/person/pic_185.jpg 7 +cartoon/person/pic_127.jpg 7 +cartoon/person/pic_113.jpg 7 +cartoon/person/pic_106.jpg 7 +cartoon/person/pic_129.jpg 7 +cartoon/person/pic_119.jpg 7 +cartoon/person/pic_125.jpg 7 +cartoon/person/pic_124.jpg 7 +cartoon/person/pic_147.jpg 7 +cartoon/person/pic_141.jpg 7 +cartoon/person/pic_140.jpg 7 +cartoon/person/pic_136.jpg 7 +cartoon/person/pic_137.jpg 7 +cartoon/person/pic_135.jpg 7 +cartoon/person/pic_133.jpg 7 +cartoon/person/pic_134.jpg 7 +cartoon/person/pic_132.jpg 7 +cartoon/person/pic_131.jpg 7 +cartoon/person/pic_146.jpg 7 +cartoon/person/pic_388.jpg 7 +cartoon/person/pic_400.jpg 7 +cartoon/person/pic_399.jpg 7 +cartoon/person/pic_402.jpg 7 +cartoon/person/pic_401.jpg 7 +cartoon/person/pic_394.jpg 7 +cartoon/person/pic_396.jpg 7 +cartoon/person/pic_395.jpg 7 +cartoon/person/pic_397.jpg 7 +cartoon/person/pic_398.jpg 7 +cartoon/person/pic_408.jpg 7 +cartoon/person/pic_403.jpg 7 +cartoon/person/pic_206.jpg 7 +cartoon/person/pic_209.jpg 7 +cartoon/person/pic_208.jpg 7 +cartoon/person/pic_207.jpg 7 +cartoon/person/pic_204.jpg 7 +cartoon/person/pic_216.jpg 7 +cartoon/person/pic_212.jpg 7 +cartoon/person/pic_210.jpg 7 +cartoon/person/pic_218.jpg 7 +cartoon/person/pic_221.jpg 7 +cartoon/person/pic_220.jpg 7 +cartoon/person/pic_222.jpg 7 +cartoon/person/pic_224.jpg 7 +cartoon/person/pic_225.jpg 7 +cartoon/person/pic_219.jpg 7 +cartoon/person/pic_226.jpg 7 +cartoon/person/pic_227.jpg 7 +cartoon/person/pic_451.jpg 7 +cartoon/person/pic_449.jpg 7 +cartoon/person/pic_450.jpg 7 +cartoon/person/pic_447.jpg 7 +cartoon/person/pic_448.jpg 7 +cartoon/person/pic_446.jpg 7 +cartoon/person/pic_453.jpg 7 +cartoon/person/pic_454.jpg 7 +cartoon/person/pic_452.jpg 7 +cartoon/person/pic_456.jpg 7 +cartoon/person/pic_458.jpg 7 +cartoon/person/pic_455.jpg 7 +cartoon/person/pic_457.jpg 7 +cartoon/person/pic_329.jpg 7 +cartoon/person/pic_330.jpg 7 +cartoon/person/pic_326.jpg 7 +cartoon/person/pic_327.jpg 7 +cartoon/person/pic_325.jpg 7 +cartoon/person/pic_328.jpg 7 +cartoon/person/pic_336.jpg 7 +cartoon/person/pic_338.jpg 7 +cartoon/person/pic_337.jpg 7 +cartoon/person/pic_340.jpg 7 +cartoon/person/pic_339.jpg 7 +cartoon/person/pic_342.jpg 7 +cartoon/person/pic_341.jpg 7 +cartoon/person/pic_343.jpg 7 +cartoon/person/pic_344.jpg 7 +cartoon/person/pic_347.jpg 7 +cartoon/person/pic_348.jpg 7 +cartoon/person/pic_350.jpg 7 +cartoon/person/pic_352.jpg 7 +cartoon/person/pic_047.jpg 7 +cartoon/person/pic_044.jpg 7 +cartoon/person/pic_045.jpg 7 +cartoon/person/pic_046.jpg 7 +cartoon/person/pic_052.jpg 7 +cartoon/person/pic_050.jpg 7 +cartoon/person/pic_053.jpg 7 +cartoon/person/pic_051.jpg 7 +cartoon/person/pic_067.jpg 7 +cartoon/person/pic_064.jpg 7 +cartoon/person/pic_063.jpg 7 +cartoon/person/pic_065.jpg 7 +cartoon/person/pic_060.jpg 7 +cartoon/person/pic_061.jpg 7 +cartoon/person/pic_059.jpg 7 +cartoon/person/pic_062.jpg 7 +cartoon/person/pic_055.jpg 7 +cartoon/person/pic_058.jpg 7 +cartoon/person/pic_054.jpg 7 +cartoon/person/pic_057.jpg 7 +cartoon/person/pic_093.jpg 7 +cartoon/person/pic_103.jpg 7 +cartoon/person/pic_104.jpg 7 +cartoon/person/pic_092.jpg 7 +cartoon/person/pic_090.jpg 7 +cartoon/person/pic_097.jpg 7 +cartoon/person/pic_080.jpg 7 +cartoon/person/pic_091.jpg 7 +cartoon/person/pic_122.jpg 7 +cartoon/person/pic_126.jpg 7 +cartoon/person/pic_112.jpg 7 +cartoon/person/pic_111.jpg 7 +cartoon/person/pic_101.jpg 7 +cartoon/person/pic_096.jpg 7 +cartoon/person/pic_130.jpg 7 +cartoon/person/pic_098.jpg 7 +cartoon/person/pic_102.jpg 7 +cartoon/person/pic_108.jpg 7 +cartoon/person/pic_114.jpg 7 +cartoon/person/pic_183.jpg 7 +cartoon/person/pic_186.jpg 7 +cartoon/person/pic_194.jpg 7 +cartoon/person/pic_188.jpg 7 +cartoon/person/pic_190.jpg 7 +cartoon/person/pic_193.jpg 7 +cartoon/person/pic_195.jpg 7 +cartoon/person/pic_199.jpg 7 +cartoon/person/pic_197.jpg 7 +cartoon/person/pic_200.jpg 7 +cartoon/person/pic_201.jpg 7 +cartoon/person/pic_203.jpg 7 +cartoon/person/pic_202.jpg 7 +cartoon/person/pic_217.jpg 7 +cartoon/person/pic_214.jpg 7 +cartoon/person/pic_215.jpg 7 +cartoon/person/pic_229.jpg 7 +cartoon/person/pic_228.jpg 7 +cartoon/person/pic_230.jpg 7 +cartoon/person/pic_236.jpg 7 +cartoon/person/pic_233.jpg 7 +cartoon/person/pic_232.jpg 7 +cartoon/person/pic_234.jpg 7 +cartoon/person/pic_231.jpg 7 +cartoon/person/pic_235.jpg 7 +cartoon/person/pic_240.jpg 7 +cartoon/person/pic_239.jpg 7 +cartoon/person/pic_237.jpg 7 +cartoon/person/pic_243.jpg 7 +cartoon/person/pic_242.jpg 7 +cartoon/person/pic_241.jpg 7 +cartoon/person/pic_244.jpg 7 +cartoon/person/pic_245.jpg 7 +cartoon/person/pic_246.jpg 7 +cartoon/person/pic_256.jpg 7 +cartoon/person/pic_254.jpg 7 +cartoon/person/pic_260.jpg 7 +cartoon/person/pic_270.jpg 7 +cartoon/person/pic_271.jpg 7 +cartoon/person/pic_273.jpg 7 +cartoon/person/pic_274.jpg 7 +cartoon/person/pic_275.jpg 7 +cartoon/person/pic_272.jpg 7 +cartoon/person/pic_276.jpg 7 +cartoon/person/pic_278.jpg 7 +cartoon/person/pic_297.jpg 7 +cartoon/person/pic_291.jpg 7 +cartoon/person/pic_293.jpg 7 +cartoon/person/pic_292.jpg 7 +cartoon/person/pic_289.jpg 7 +cartoon/person/pic_285.jpg 7 +cartoon/person/pic_283.jpg 7 +cartoon/person/pic_282.jpg 7 +cartoon/person/pic_286.jpg 7 +cartoon/person/pic_281.jpg 7 +cartoon/person/pic_280.jpg 7 +cartoon/person/pic_279.jpg 7 +cartoon/person/pic_277.jpg 7 +cartoon/person/pic_301.jpg 7 +cartoon/person/pic_298.jpg 7 +cartoon/person/pic_302.jpg 7 +cartoon/person/pic_294.jpg 7 +cartoon/person/pic_299.jpg 7 +cartoon/person/pic_284.jpg 7 +cartoon/person/pic_287.jpg 7 +cartoon/person/pic_305.jpg 7 +cartoon/person/pic_296.jpg 7 +cartoon/person/pic_300.jpg 7 +cartoon/person/pic_295.jpg 7 +cartoon/person/pic_303.jpg 7 +cartoon/person/pic_315.jpg 7 +cartoon/person/pic_314.jpg 7 +cartoon/person/pic_310.jpg 7 +cartoon/person/pic_405.jpg 7 +cartoon/person/pic_404.jpg 7 +cartoon/person/pic_406.jpg 7 +cartoon/person/pic_413.jpg 7 +cartoon/person/pic_411.jpg 7 +cartoon/person/pic_410.jpg 7 +cartoon/person/pic_409.jpg 7 +cartoon/person/pic_412.jpg 7 +cartoon/person/pic_426.jpg 7 +cartoon/person/pic_428.jpg 7 +cartoon/person/pic_425.jpg 7 +cartoon/person/pic_424.jpg 7 +cartoon/person/pic_421.jpg 7 +cartoon/person/pic_417.jpg 7 +cartoon/person/pic_419.jpg 7 +cartoon/person/pic_418.jpg 7 +cartoon/person/pic_416.jpg 7 +cartoon/person/pic_351.jpg 7 +cartoon/person/pic_349.jpg 7 +cartoon/person/pic_363.jpg 7 +cartoon/person/pic_358.jpg 7 +cartoon/person/pic_357.jpg 7 +cartoon/person/pic_354.jpg 7 +cartoon/person/pic_353.jpg 7 +cartoon/person/pic_360.jpg 7 +cartoon/person/pic_362.jpg 7 +cartoon/person/pic_359.jpg 7 +cartoon/person/pic_366.jpg 7 +cartoon/person/pic_375.jpg 7 +cartoon/person/pic_376.jpg 7 +cartoon/person/pic_372.jpg 7 +cartoon/person/pic_371.jpg 7 +cartoon/person/pic_369.jpg 7 +cartoon/person/pic_368.jpg 7 +cartoon/person/pic_364.jpg 7 +cartoon/person/pic_251.jpg 7 +cartoon/person/pic_250.jpg 7 +cartoon/person/pic_252.jpg 7 +cartoon/person/pic_248.jpg 7 +cartoon/person/pic_247.jpg 7 +cartoon/person/pic_249.jpg 7 +cartoon/person/pic_257.jpg 7 +cartoon/person/pic_253.jpg 7 +cartoon/person/pic_259.jpg 7 +cartoon/person/pic_268.jpg 7 +cartoon/person/pic_264.jpg 7 +cartoon/person/pic_265.jpg 7 +cartoon/person/pic_262.jpg 7 +cartoon/person/pic_261.jpg 7 +cartoon/person/pic_255.jpg 7 diff --git a/domainlab/zdata/pacs_split/cartoon_train_kfold.txt b/domainlab/zdata/pacs_split/cartoon_train_kfold.txt new file mode 100644 index 000000000..48ceb2f88 --- /dev/null +++ b/domainlab/zdata/pacs_split/cartoon_train_kfold.txt @@ -0,0 +1,2107 @@ +cartoon/dog/pic_056.jpg 1 +cartoon/dog/pic_052.jpg 1 +cartoon/dog/pic_049.jpg 1 +cartoon/dog/pic_019.jpg 1 +cartoon/dog/pic_023.jpg 1 +cartoon/dog/pic_048.jpg 1 +cartoon/dog/pic_044.jpg 1 +cartoon/dog/pic_042.jpg 1 +cartoon/dog/pic_038.jpg 1 +cartoon/dog/pic_033.jpg 1 +cartoon/dog/pic_040.jpg 1 +cartoon/dog/pic_055.jpg 1 +cartoon/dog/pic_053.jpg 1 +cartoon/dog/pic_041.jpg 1 +cartoon/dog/pic_039.jpg 1 +cartoon/dog/pic_111.jpg 1 +cartoon/dog/pic_109.jpg 1 +cartoon/dog/pic_114.jpg 1 +cartoon/dog/pic_140.jpg 1 +cartoon/dog/pic_142.jpg 1 +cartoon/dog/pic_138.jpg 1 +cartoon/dog/pic_135.jpg 1 +cartoon/dog/pic_129.jpg 1 +cartoon/dog/pic_125.jpg 1 +cartoon/dog/pic_122.jpg 1 +cartoon/dog/pic_121.jpg 1 +cartoon/dog/pic_117.jpg 1 +cartoon/dog/pic_115.jpg 1 +cartoon/dog/pic_112.jpg 1 +cartoon/dog/pic_120.jpg 1 +cartoon/dog/pic_143.jpg 1 +cartoon/dog/pic_346.jpg 1 +cartoon/dog/pic_349.jpg 1 +cartoon/dog/pic_347.jpg 1 +cartoon/dog/pic_340.jpg 1 +cartoon/dog/pic_332.jpg 1 +cartoon/dog/pic_358.jpg 1 +cartoon/dog/pic_351.jpg 1 +cartoon/dog/pic_361.jpg 1 +cartoon/dog/pic_360.jpg 1 +cartoon/dog/pic_446.jpg 1 +cartoon/dog/pic_430.jpg 1 +cartoon/dog/pic_427.jpg 1 +cartoon/dog/pic_381.jpg 1 +cartoon/dog/pic_379.jpg 1 +cartoon/dog/pic_373.jpg 1 +cartoon/dog/pic_400.jpg 1 +cartoon/dog/pic_429.jpg 1 +cartoon/dog/pic_442.jpg 1 +cartoon/dog/pic_134.jpg 1 +cartoon/dog/pic_137.jpg 1 +cartoon/dog/pic_136.jpg 1 +cartoon/dog/pic_118.jpg 1 +cartoon/dog/pic_126.jpg 1 +cartoon/dog/pic_133.jpg 1 +cartoon/dog/pic_124.jpg 1 +cartoon/dog/pic_127.jpg 1 +cartoon/dog/pic_139.jpg 1 +cartoon/dog/pic_145.jpg 1 +cartoon/dog/pic_132.jpg 1 +cartoon/dog/pic_141.jpg 1 +cartoon/dog/pic_152.jpg 1 +cartoon/dog/pic_151.jpg 1 +cartoon/dog/pic_153.jpg 1 +cartoon/dog/pic_155.jpg 1 +cartoon/dog/pic_217.jpg 1 +cartoon/dog/pic_218.jpg 1 +cartoon/dog/pic_244.jpg 1 +cartoon/dog/pic_246.jpg 1 +cartoon/dog/pic_245.jpg 1 +cartoon/dog/pic_243.jpg 1 +cartoon/dog/pic_241.jpg 1 +cartoon/dog/pic_296.jpg 1 +cartoon/dog/pic_300.jpg 1 +cartoon/dog/pic_277.jpg 1 +cartoon/dog/pic_290.jpg 1 +cartoon/dog/pic_284.jpg 1 +cartoon/dog/pic_256.jpg 1 +cartoon/dog/pic_255.jpg 1 +cartoon/dog/pic_261.jpg 1 +cartoon/dog/pic_294.jpg 1 +cartoon/dog/pic_247.jpg 1 +cartoon/dog/pic_267.jpg 1 +cartoon/dog/pic_265.jpg 1 +cartoon/dog/pic_208.jpg 1 +cartoon/dog/pic_205.jpg 1 +cartoon/dog/pic_207.jpg 1 +cartoon/dog/pic_206.jpg 1 +cartoon/dog/pic_209.jpg 1 +cartoon/dog/pic_224.jpg 1 +cartoon/dog/pic_223.jpg 1 +cartoon/dog/pic_222.jpg 1 +cartoon/dog/pic_215.jpg 1 +cartoon/dog/pic_221.jpg 1 +cartoon/dog/pic_214.jpg 1 +cartoon/dog/pic_212.jpg 1 +cartoon/dog/pic_211.jpg 1 +cartoon/dog/pic_210.jpg 1 +cartoon/dog/pic_213.jpg 1 +cartoon/dog/pic_239.jpg 1 +cartoon/dog/pic_237.jpg 1 +cartoon/dog/pic_234.jpg 1 +cartoon/dog/pic_235.jpg 1 +cartoon/dog/pic_007.jpg 1 +cartoon/dog/pic_008.jpg 1 +cartoon/dog/pic_009.jpg 1 +cartoon/dog/pic_010.jpg 1 +cartoon/dog/pic_011.jpg 1 +cartoon/dog/pic_012.jpg 1 +cartoon/dog/pic_013.jpg 1 +cartoon/dog/pic_014.jpg 1 +cartoon/dog/pic_015.jpg 1 +cartoon/dog/pic_016.jpg 1 +cartoon/dog/pic_017.jpg 1 +cartoon/dog/pic_018.jpg 1 +cartoon/dog/pic_032.jpg 1 +cartoon/dog/pic_030.jpg 1 +cartoon/dog/pic_021.jpg 1 +cartoon/dog/pic_024.jpg 1 +cartoon/dog/pic_028.jpg 1 +cartoon/dog/pic_026.jpg 1 +cartoon/dog/pic_022.jpg 1 +cartoon/dog/pic_447.jpg 1 +cartoon/dog/pic_449.jpg 1 +cartoon/dog/pic_450.jpg 1 +cartoon/dog/pic_166.jpg 1 +cartoon/dog/pic_171.jpg 1 +cartoon/dog/pic_167.jpg 1 +cartoon/dog/pic_168.jpg 1 +cartoon/dog/pic_172.jpg 1 +cartoon/dog/pic_170.jpg 1 +cartoon/dog/pic_169.jpg 1 +cartoon/dog/pic_173.jpg 1 +cartoon/dog/pic_176.jpg 1 +cartoon/dog/pic_175.jpg 1 +cartoon/dog/pic_180.jpg 1 +cartoon/dog/pic_179.jpg 1 +cartoon/dog/pic_178.jpg 1 +cartoon/dog/pic_177.jpg 1 +cartoon/dog/pic_183.jpg 1 +cartoon/dog/pic_184.jpg 1 +cartoon/dog/pic_182.jpg 1 +cartoon/dog/pic_220.jpg 1 +cartoon/dog/pic_219.jpg 1 +cartoon/dog/pic_216.jpg 1 +cartoon/dog/pic_273.jpg 1 +cartoon/dog/pic_272.jpg 1 +cartoon/dog/pic_275.jpg 1 +cartoon/dog/pic_274.jpg 1 +cartoon/dog/pic_280.jpg 1 +cartoon/dog/pic_279.jpg 1 +cartoon/dog/pic_281.jpg 1 +cartoon/dog/pic_282.jpg 1 +cartoon/dog/pic_327.jpg 1 +cartoon/dog/pic_329.jpg 1 +cartoon/dog/pic_326.jpg 1 +cartoon/dog/pic_328.jpg 1 +cartoon/dog/pic_335.jpg 1 +cartoon/dog/pic_338.jpg 1 +cartoon/dog/pic_339.jpg 1 +cartoon/dog/pic_337.jpg 1 +cartoon/dog/pic_374.jpg 1 +cartoon/dog/pic_372.jpg 1 +cartoon/dog/pic_371.jpg 1 +cartoon/dog/pic_369.jpg 1 +cartoon/dog/pic_368.jpg 1 +cartoon/dog/pic_367.jpg 1 +cartoon/dog/pic_366.jpg 1 +cartoon/dog/pic_365.jpg 1 +cartoon/dog/pic_364.jpg 1 +cartoon/dog/pic_437.jpg 1 +cartoon/dog/pic_431.jpg 1 +cartoon/dog/pic_413.jpg 1 +cartoon/dog/pic_394.jpg 1 +cartoon/dog/pic_428.jpg 1 +cartoon/dog/pic_387.jpg 1 +cartoon/dog/pic_380.jpg 1 +cartoon/dog/pic_376.jpg 1 +cartoon/dog/pic_425.jpg 1 +cartoon/dog/pic_414.jpg 1 +cartoon/dog/pic_398.jpg 1 +cartoon/dog/pic_317.jpg 1 +cartoon/dog/pic_318.jpg 1 +cartoon/dog/pic_323.jpg 1 +cartoon/dog/pic_363.jpg 1 +cartoon/dog/pic_357.jpg 1 +cartoon/dog/pic_356.jpg 1 +cartoon/dog/pic_354.jpg 1 +cartoon/dog/pic_352.jpg 1 +cartoon/dog/pic_353.jpg 1 +cartoon/dog/pic_348.jpg 1 +cartoon/dog/pic_345.jpg 1 +cartoon/dog/pic_344.jpg 1 +cartoon/dog/pic_343.jpg 1 +cartoon/dog/pic_341.jpg 1 +cartoon/dog/pic_333.jpg 1 +cartoon/dog/pic_334.jpg 1 +cartoon/dog/pic_331.jpg 1 +cartoon/dog/pic_350.jpg 1 +cartoon/dog/pic_181.jpg 1 +cartoon/dog/pic_188.jpg 1 +cartoon/dog/pic_190.jpg 1 +cartoon/dog/pic_186.jpg 1 +cartoon/dog/pic_185.jpg 1 +cartoon/dog/pic_189.jpg 1 +cartoon/dog/pic_192.jpg 1 +cartoon/dog/pic_191.jpg 1 +cartoon/dog/pic_193.jpg 1 +cartoon/dog/pic_195.jpg 1 +cartoon/dog/pic_201.jpg 1 +cartoon/dog/pic_200.jpg 1 +cartoon/dog/pic_197.jpg 1 +cartoon/dog/pic_198.jpg 1 +cartoon/dog/pic_196.jpg 1 +cartoon/dog/pic_202.jpg 1 +cartoon/dog/pic_204.jpg 1 +cartoon/dog/pic_203.jpg 1 +cartoon/dog/pic_034.jpg 1 +cartoon/dog/pic_027.jpg 1 +cartoon/dog/pic_029.jpg 1 +cartoon/dog/pic_050.jpg 1 +cartoon/dog/pic_035.jpg 1 +cartoon/dog/pic_037.jpg 1 +cartoon/dog/pic_051.jpg 1 +cartoon/dog/pic_045.jpg 1 +cartoon/dog/pic_058.jpg 1 +cartoon/dog/pic_057.jpg 1 +cartoon/dog/pic_059.jpg 1 +cartoon/dog/pic_062.jpg 1 +cartoon/dog/pic_063.jpg 1 +cartoon/dog/pic_060.jpg 1 +cartoon/dog/pic_061.jpg 1 +cartoon/dog/pic_065.jpg 1 +cartoon/dog/pic_064.jpg 1 +cartoon/dog/pic_068.jpg 1 +cartoon/dog/pic_067.jpg 1 +cartoon/dog/pic_432.jpg 1 +cartoon/dog/pic_424.jpg 1 +cartoon/dog/pic_445.jpg 1 +cartoon/dog/pic_397.jpg 1 +cartoon/dog/pic_389.jpg 1 +cartoon/dog/pic_395.jpg 1 +cartoon/dog/pic_435.jpg 1 +cartoon/dog/pic_399.jpg 1 +cartoon/dog/pic_411.jpg 1 +cartoon/dog/pic_434.jpg 1 +cartoon/dog/pic_444.jpg 1 +cartoon/dog/pic_401.jpg 1 +cartoon/dog/pic_396.jpg 1 +cartoon/dog/pic_426.jpg 1 +cartoon/dog/pic_433.jpg 1 +cartoon/dog/pic_443.jpg 1 +cartoon/dog/pic_412.jpg 1 +cartoon/dog/pic_148.jpg 1 +cartoon/dog/pic_146.jpg 1 +cartoon/dog/pic_418.jpg 1 +cartoon/dog/pic_156.jpg 1 +cartoon/dog/pic_149.jpg 1 +cartoon/dog/pic_160.jpg 1 +cartoon/dog/pic_161.jpg 1 +cartoon/dog/pic_163.jpg 1 +cartoon/dog/pic_165.jpg 1 +cartoon/dog/pic_164.jpg 1 +cartoon/dog/pic_419.jpg 1 +cartoon/dog/pic_422.jpg 1 +cartoon/dog/pic_420.jpg 1 +cartoon/dog/pic_421.jpg 1 +cartoon/dog/pic_423.jpg 1 +cartoon/dog/pic_439.jpg 1 +cartoon/dog/pic_438.jpg 1 +cartoon/dog/pic_441.jpg 1 +cartoon/dog/pic_440.jpg 1 +cartoon/dog/pic_242.jpg 1 +cartoon/dog/pic_260.jpg 1 +cartoon/dog/pic_293.jpg 1 +cartoon/dog/pic_278.jpg 1 +cartoon/dog/pic_269.jpg 1 +cartoon/dog/pic_292.jpg 1 +cartoon/dog/pic_268.jpg 1 +cartoon/dog/pic_291.jpg 1 +cartoon/dog/pic_289.jpg 1 +cartoon/dog/pic_266.jpg 1 +cartoon/dog/pic_258.jpg 1 +cartoon/dog/pic_264.jpg 1 +cartoon/dog/pic_287.jpg 1 +cartoon/dog/pic_298.jpg 1 +cartoon/dog/pic_288.jpg 1 +cartoon/dog/pic_295.jpg 1 +cartoon/dog/pic_299.jpg 1 +cartoon/dog/pic_306.jpg 1 +cartoon/dog/pic_305.jpg 1 +cartoon/dog/pic_304.jpg 1 +cartoon/dog/pic_302.jpg 1 +cartoon/dog/pic_303.jpg 1 +cartoon/dog/pic_308.jpg 1 +cartoon/dog/pic_309.jpg 1 +cartoon/dog/pic_330.jpg 1 +cartoon/dog/pic_324.jpg 1 +cartoon/dog/pic_322.jpg 1 +cartoon/dog/pic_319.jpg 1 +cartoon/dog/pic_320.jpg 1 +cartoon/dog/pic_315.jpg 1 +cartoon/dog/pic_313.jpg 1 +cartoon/dog/pic_314.jpg 1 +cartoon/dog/pic_310.jpg 1 +cartoon/dog/pic_325.jpg 1 +cartoon/dog/pic_316.jpg 1 +cartoon/dog/pic_321.jpg 1 +cartoon/dog/pic_312.jpg 1 +cartoon/dog/pic_069.jpg 1 +cartoon/dog/pic_066.jpg 1 +cartoon/dog/pic_082.jpg 1 +cartoon/dog/pic_078.jpg 1 +cartoon/dog/pic_076.jpg 1 +cartoon/dog/pic_077.jpg 1 +cartoon/dog/pic_074.jpg 1 +cartoon/dog/pic_073.jpg 1 +cartoon/dog/pic_072.jpg 1 +cartoon/dog/pic_071.jpg 1 +cartoon/dog/pic_079.jpg 1 +cartoon/dog/pic_080.jpg 1 +cartoon/dog/pic_083.jpg 1 +cartoon/dog/pic_081.jpg 1 +cartoon/dog/pic_084.jpg 1 +cartoon/dog/pic_085.jpg 1 +cartoon/dog/pic_086.jpg 1 +cartoon/dog/pic_087.jpg 1 +cartoon/dog/pic_088.jpg 1 +cartoon/dog/pic_089.jpg 1 +cartoon/dog/pic_090.jpg 1 +cartoon/dog/pic_094.jpg 1 +cartoon/dog/pic_093.jpg 1 +cartoon/dog/pic_091.jpg 1 +cartoon/dog/pic_092.jpg 1 +cartoon/dog/pic_108.jpg 1 +cartoon/dog/pic_105.jpg 1 +cartoon/dog/pic_104.jpg 1 +cartoon/dog/pic_103.jpg 1 +cartoon/dog/pic_099.jpg 1 +cartoon/dog/pic_101.jpg 1 +cartoon/dog/pic_098.jpg 1 +cartoon/dog/pic_097.jpg 1 +cartoon/dog/pic_096.jpg 1 +cartoon/dog/pic_095.jpg 1 +cartoon/dog/pic_102.jpg 1 +cartoon/dog/pic_106.jpg 1 +cartoon/dog/pic_107.jpg 1 +cartoon/dog/pic_100.jpg 1 +cartoon/dog/pic_113.jpg 1 +cartoon/dog/pic_110.jpg 1 +cartoon/elephant/pic_421.jpg 2 +cartoon/elephant/pic_419.jpg 2 +cartoon/elephant/pic_418.jpg 2 +cartoon/elephant/pic_026.jpg 2 +cartoon/elephant/pic_028.jpg 2 +cartoon/elephant/pic_024.jpg 2 +cartoon/elephant/pic_027.jpg 2 +cartoon/elephant/pic_021.jpg 2 +cartoon/elephant/pic_030.jpg 2 +cartoon/elephant/pic_036.jpg 2 +cartoon/elephant/pic_037.jpg 2 +cartoon/elephant/pic_033.jpg 2 +cartoon/elephant/pic_056.jpg 2 +cartoon/elephant/pic_052.jpg 2 +cartoon/elephant/pic_048.jpg 2 +cartoon/elephant/pic_040.jpg 2 +cartoon/elephant/pic_046.jpg 2 +cartoon/elephant/pic_045.jpg 2 +cartoon/elephant/pic_043.jpg 2 +cartoon/elephant/pic_044.jpg 2 +cartoon/elephant/pic_042.jpg 2 +cartoon/elephant/pic_034.jpg 2 +cartoon/elephant/pic_025.jpg 2 +cartoon/elephant/pic_325.jpg 2 +cartoon/elephant/pic_328.jpg 2 +cartoon/elephant/pic_329.jpg 2 +cartoon/elephant/pic_330.jpg 2 +cartoon/elephant/pic_331.jpg 2 +cartoon/elephant/pic_332.jpg 2 +cartoon/elephant/pic_333.jpg 2 +cartoon/elephant/pic_338.jpg 2 +cartoon/elephant/pic_336.jpg 2 +cartoon/elephant/pic_337.jpg 2 +cartoon/elephant/pic_335.jpg 2 +cartoon/elephant/pic_334.jpg 2 +cartoon/elephant/pic_342.jpg 2 +cartoon/elephant/pic_339.jpg 2 +cartoon/elephant/pic_340.jpg 2 +cartoon/elephant/pic_341.jpg 2 +cartoon/elephant/pic_343.jpg 2 +cartoon/elephant/pic_351.jpg 2 +cartoon/elephant/pic_345.jpg 2 +cartoon/elephant/pic_350.jpg 2 +cartoon/elephant/pic_280.jpg 2 +cartoon/elephant/pic_203.jpg 2 +cartoon/elephant/pic_204.jpg 2 +cartoon/elephant/pic_215.jpg 2 +cartoon/elephant/pic_207.jpg 2 +cartoon/elephant/pic_208.jpg 2 +cartoon/elephant/pic_206.jpg 2 +cartoon/elephant/pic_205.jpg 2 +cartoon/elephant/pic_216.jpg 2 +cartoon/elephant/pic_223.jpg 2 +cartoon/elephant/pic_222.jpg 2 +cartoon/elephant/pic_221.jpg 2 +cartoon/elephant/pic_285.jpg 2 +cartoon/elephant/pic_282.jpg 2 +cartoon/elephant/pic_218.jpg 2 +cartoon/elephant/pic_217.jpg 2 +cartoon/elephant/pic_224.jpg 2 +cartoon/elephant/pic_286.jpg 2 +cartoon/elephant/pic_392.jpg 2 +cartoon/elephant/pic_390.jpg 2 +cartoon/elephant/pic_395.jpg 2 +cartoon/elephant/pic_393.jpg 2 +cartoon/elephant/pic_391.jpg 2 +cartoon/elephant/pic_394.jpg 2 +cartoon/elephant/pic_403.jpg 2 +cartoon/elephant/pic_401.jpg 2 +cartoon/elephant/pic_400.jpg 2 +cartoon/elephant/pic_399.jpg 2 +cartoon/elephant/pic_396.jpg 2 +cartoon/elephant/pic_397.jpg 2 +cartoon/elephant/pic_398.jpg 2 +cartoon/elephant/pic_402.jpg 2 +cartoon/elephant/pic_407.jpg 2 +cartoon/elephant/pic_406.jpg 2 +cartoon/elephant/pic_405.jpg 2 +cartoon/elephant/pic_404.jpg 2 +cartoon/elephant/pic_415.jpg 2 +cartoon/elephant/pic_416.jpg 2 +cartoon/elephant/pic_349.jpg 2 +cartoon/elephant/pic_348.jpg 2 +cartoon/elephant/pic_347.jpg 2 +cartoon/elephant/pic_346.jpg 2 +cartoon/elephant/pic_344.jpg 2 +cartoon/elephant/pic_356.jpg 2 +cartoon/elephant/pic_355.jpg 2 +cartoon/elephant/pic_354.jpg 2 +cartoon/elephant/pic_352.jpg 2 +cartoon/elephant/pic_359.jpg 2 +cartoon/elephant/pic_357.jpg 2 +cartoon/elephant/pic_362.jpg 2 +cartoon/elephant/pic_360.jpg 2 +cartoon/elephant/pic_366.jpg 2 +cartoon/elephant/pic_365.jpg 2 +cartoon/elephant/pic_364.jpg 2 +cartoon/elephant/pic_363.jpg 2 +cartoon/elephant/pic_367.jpg 2 +cartoon/elephant/pic_064.jpg 2 +cartoon/elephant/pic_063.jpg 2 +cartoon/elephant/pic_062.jpg 2 +cartoon/elephant/pic_061.jpg 2 +cartoon/elephant/pic_118.jpg 2 +cartoon/elephant/pic_111.jpg 2 +cartoon/elephant/pic_100.jpg 2 +cartoon/elephant/pic_098.jpg 2 +cartoon/elephant/pic_096.jpg 2 +cartoon/elephant/pic_092.jpg 2 +cartoon/elephant/pic_088.jpg 2 +cartoon/elephant/pic_086.jpg 2 +cartoon/elephant/pic_083.jpg 2 +cartoon/elephant/pic_080.jpg 2 +cartoon/elephant/pic_079.jpg 2 +cartoon/elephant/pic_078.jpg 2 +cartoon/elephant/pic_076.jpg 2 +cartoon/elephant/pic_068.jpg 2 +cartoon/elephant/pic_072.jpg 2 +cartoon/elephant/pic_074.jpg 2 +cartoon/elephant/pic_071.jpg 2 +cartoon/elephant/pic_001.jpg 2 +cartoon/elephant/pic_002.jpg 2 +cartoon/elephant/pic_003.jpg 2 +cartoon/elephant/pic_004.jpg 2 +cartoon/elephant/pic_005.jpg 2 +cartoon/elephant/pic_007.jpg 2 +cartoon/elephant/pic_008.jpg 2 +cartoon/elephant/pic_009.jpg 2 +cartoon/elephant/pic_010.jpg 2 +cartoon/elephant/pic_011.jpg 2 +cartoon/elephant/pic_012.jpg 2 +cartoon/elephant/pic_013.jpg 2 +cartoon/elephant/pic_014.jpg 2 +cartoon/elephant/pic_015.jpg 2 +cartoon/elephant/pic_016.jpg 2 +cartoon/elephant/pic_017.jpg 2 +cartoon/elephant/pic_019.jpg 2 +cartoon/elephant/pic_020.jpg 2 +cartoon/elephant/pic_038.jpg 2 +cartoon/elephant/pic_220.jpg 2 +cartoon/elephant/pic_219.jpg 2 +cartoon/elephant/pic_284.jpg 2 +cartoon/elephant/pic_233.jpg 2 +cartoon/elephant/pic_232.jpg 2 +cartoon/elephant/pic_290.jpg 2 +cartoon/elephant/pic_292.jpg 2 +cartoon/elephant/pic_231.jpg 2 +cartoon/elephant/pic_228.jpg 2 +cartoon/elephant/pic_230.jpg 2 +cartoon/elephant/pic_229.jpg 2 +cartoon/elephant/pic_289.jpg 2 +cartoon/elephant/pic_291.jpg 2 +cartoon/elephant/pic_236.jpg 2 +cartoon/elephant/pic_235.jpg 2 +cartoon/elephant/pic_294.jpg 2 +cartoon/elephant/pic_239.jpg 2 +cartoon/elephant/pic_238.jpg 2 +cartoon/elephant/pic_295.jpg 2 +cartoon/elephant/pic_296.jpg 2 +cartoon/elephant/pic_183.jpg 2 +cartoon/elephant/pic_182.jpg 2 +cartoon/elephant/pic_190.jpg 2 +cartoon/elephant/pic_198.jpg 2 +cartoon/elephant/pic_197.jpg 2 +cartoon/elephant/pic_196.jpg 2 +cartoon/elephant/pic_273.jpg 2 +cartoon/elephant/pic_194.jpg 2 +cartoon/elephant/pic_272.jpg 2 +cartoon/elephant/pic_195.jpg 2 +cartoon/elephant/pic_192.jpg 2 +cartoon/elephant/pic_276.jpg 2 +cartoon/elephant/pic_279.jpg 2 +cartoon/elephant/pic_202.jpg 2 +cartoon/elephant/pic_275.jpg 2 +cartoon/elephant/pic_274.jpg 2 +cartoon/elephant/pic_200.jpg 2 +cartoon/elephant/pic_201.jpg 2 +cartoon/elephant/pic_199.jpg 2 +cartoon/elephant/pic_433.jpg 2 +cartoon/elephant/pic_434.jpg 2 +cartoon/elephant/pic_435.jpg 2 +cartoon/elephant/pic_432.jpg 2 +cartoon/elephant/pic_439.jpg 2 +cartoon/elephant/pic_427.jpg 2 +cartoon/elephant/pic_440.jpg 2 +cartoon/elephant/pic_438.jpg 2 +cartoon/elephant/pic_426.jpg 2 +cartoon/elephant/pic_449.jpg 2 +cartoon/elephant/pic_447.jpg 2 +cartoon/elephant/pic_448.jpg 2 +cartoon/elephant/pic_444.jpg 2 +cartoon/elephant/pic_443.jpg 2 +cartoon/elephant/pic_442.jpg 2 +cartoon/elephant/pic_446.jpg 2 +cartoon/elephant/pic_464.jpg 2 +cartoon/elephant/pic_368.jpg 2 +cartoon/elephant/pic_370.jpg 2 +cartoon/elephant/pic_372.jpg 2 +cartoon/elephant/pic_373.jpg 2 +cartoon/elephant/pic_374.jpg 2 +cartoon/elephant/pic_376.jpg 2 +cartoon/elephant/pic_375.jpg 2 +cartoon/elephant/pic_378.jpg 2 +cartoon/elephant/pic_377.jpg 2 +cartoon/elephant/pic_381.jpg 2 +cartoon/elephant/pic_382.jpg 2 +cartoon/elephant/pic_383.jpg 2 +cartoon/elephant/pic_384.jpg 2 +cartoon/elephant/pic_385.jpg 2 +cartoon/elephant/pic_389.jpg 2 +cartoon/elephant/pic_388.jpg 2 +cartoon/elephant/pic_387.jpg 2 +cartoon/elephant/pic_023.jpg 2 +cartoon/elephant/pic_022.jpg 2 +cartoon/elephant/pic_039.jpg 2 +cartoon/elephant/pic_053.jpg 2 +cartoon/elephant/pic_049.jpg 2 +cartoon/elephant/pic_047.jpg 2 +cartoon/elephant/pic_041.jpg 2 +cartoon/elephant/pic_050.jpg 2 +cartoon/elephant/pic_035.jpg 2 +cartoon/elephant/pic_057.jpg 2 +cartoon/elephant/pic_032.jpg 2 +cartoon/elephant/pic_055.jpg 2 +cartoon/elephant/pic_058.jpg 2 +cartoon/elephant/pic_029.jpg 2 +cartoon/elephant/pic_051.jpg 2 +cartoon/elephant/pic_054.jpg 2 +cartoon/elephant/pic_059.jpg 2 +cartoon/elephant/pic_060.jpg 2 +cartoon/elephant/pic_066.jpg 2 +cartoon/elephant/pic_065.jpg 2 +cartoon/elephant/pic_085.jpg 2 +cartoon/elephant/pic_094.jpg 2 +cartoon/elephant/pic_091.jpg 2 +cartoon/elephant/pic_110.jpg 2 +cartoon/elephant/pic_147.jpg 2 +cartoon/elephant/pic_149.jpg 2 +cartoon/elephant/pic_140.jpg 2 +cartoon/elephant/pic_135.jpg 2 +cartoon/elephant/pic_115.jpg 2 +cartoon/elephant/pic_089.jpg 2 +cartoon/elephant/pic_107.jpg 2 +cartoon/elephant/pic_104.jpg 2 +cartoon/elephant/pic_095.jpg 2 +cartoon/elephant/pic_142.jpg 2 +cartoon/elephant/pic_081.jpg 2 +cartoon/elephant/pic_090.jpg 2 +cartoon/elephant/pic_097.jpg 2 +cartoon/elephant/pic_106.jpg 2 +cartoon/elephant/pic_151.jpg 2 +cartoon/elephant/pic_129.jpg 2 +cartoon/elephant/pic_121.jpg 2 +cartoon/elephant/pic_259.jpg 2 +cartoon/elephant/pic_174.jpg 2 +cartoon/elephant/pic_260.jpg 2 +cartoon/elephant/pic_180.jpg 2 +cartoon/elephant/pic_178.jpg 2 +cartoon/elephant/pic_177.jpg 2 +cartoon/elephant/pic_176.jpg 2 +cartoon/elephant/pic_264.jpg 2 +cartoon/elephant/pic_175.jpg 2 +cartoon/elephant/pic_263.jpg 2 +cartoon/elephant/pic_262.jpg 2 +cartoon/elephant/pic_261.jpg 2 +cartoon/elephant/pic_181.jpg 2 +cartoon/elephant/pic_268.jpg 2 +cartoon/elephant/pic_179.jpg 2 +cartoon/elephant/pic_269.jpg 2 +cartoon/elephant/pic_191.jpg 2 +cartoon/elephant/pic_271.jpg 2 +cartoon/elephant/pic_184.jpg 2 +cartoon/elephant/pic_185.jpg 2 +cartoon/elephant/pic_270.jpg 2 +cartoon/elephant/pic_070.jpg 2 +cartoon/elephant/pic_067.jpg 2 +cartoon/elephant/pic_069.jpg 2 +cartoon/elephant/pic_137.jpg 2 +cartoon/elephant/pic_136.jpg 2 +cartoon/elephant/pic_108.jpg 2 +cartoon/elephant/pic_116.jpg 2 +cartoon/elephant/pic_117.jpg 2 +cartoon/elephant/pic_103.jpg 2 +cartoon/elephant/pic_093.jpg 2 +cartoon/elephant/pic_099.jpg 2 +cartoon/elephant/pic_084.jpg 2 +cartoon/elephant/pic_102.jpg 2 +cartoon/elephant/pic_087.jpg 2 +cartoon/elephant/pic_082.jpg 2 +cartoon/elephant/pic_073.jpg 2 +cartoon/elephant/pic_075.jpg 2 +cartoon/elephant/pic_077.jpg 2 +cartoon/elephant/pic_473.jpg 2 +cartoon/elephant/pic_475.jpg 2 +cartoon/elephant/pic_474.jpg 2 +cartoon/elephant/pic_476.jpg 2 +cartoon/elephant/pic_481.jpg 2 +cartoon/elephant/pic_480.jpg 2 +cartoon/elephant/pic_478.jpg 2 +cartoon/elephant/pic_479.jpg 2 +cartoon/elephant/pic_477.jpg 2 +cartoon/elephant/pic_482.jpg 2 +cartoon/elephant/pic_485.jpg 2 +cartoon/elephant/pic_484.jpg 2 +cartoon/elephant/pic_483.jpg 2 +cartoon/elephant/pic_486.jpg 2 +cartoon/elephant/pic_487.jpg 2 +cartoon/elephant/pic_491.jpg 2 +cartoon/elephant/pic_493.jpg 2 +cartoon/elephant/pic_305.jpg 2 +cartoon/elephant/pic_307.jpg 2 +cartoon/elephant/pic_311.jpg 2 +cartoon/elephant/pic_308.jpg 2 +cartoon/elephant/pic_312.jpg 2 +cartoon/elephant/pic_310.jpg 2 +cartoon/elephant/pic_313.jpg 2 +cartoon/elephant/pic_309.jpg 2 +cartoon/elephant/pic_314.jpg 2 +cartoon/elephant/pic_316.jpg 2 +cartoon/elephant/pic_319.jpg 2 +cartoon/elephant/pic_318.jpg 2 +cartoon/elephant/pic_322.jpg 2 +cartoon/elephant/pic_320.jpg 2 +cartoon/elephant/pic_324.jpg 2 +cartoon/elephant/pic_323.jpg 2 +cartoon/elephant/pic_327.jpg 2 +cartoon/elephant/pic_326.jpg 2 +cartoon/elephant/pic_114.jpg 2 +cartoon/elephant/pic_146.jpg 2 +cartoon/elephant/pic_131.jpg 2 +cartoon/elephant/pic_132.jpg 2 +cartoon/elephant/pic_213.jpg 2 +cartoon/elephant/pic_210.jpg 2 +cartoon/elephant/pic_186.jpg 2 +cartoon/elephant/pic_188.jpg 2 +cartoon/elephant/pic_214.jpg 2 +cartoon/elephant/pic_152.jpg 2 +cartoon/elephant/pic_119.jpg 2 +cartoon/elephant/pic_133.jpg 2 +cartoon/elephant/pic_139.jpg 2 +cartoon/elephant/pic_212.jpg 2 +cartoon/elephant/pic_209.jpg 2 +cartoon/elephant/pic_126.jpg 2 +cartoon/elephant/pic_130.jpg 2 +cartoon/elephant/pic_187.jpg 2 +cartoon/elephant/pic_159.jpg 2 +cartoon/elephant/pic_462.jpg 2 +cartoon/elephant/pic_463.jpg 2 +cartoon/elephant/pic_460.jpg 2 +cartoon/elephant/pic_461.jpg 2 +cartoon/elephant/pic_458.jpg 2 +cartoon/elephant/pic_456.jpg 2 +cartoon/elephant/pic_454.jpg 2 +cartoon/elephant/pic_453.jpg 2 +cartoon/elephant/pic_452.jpg 2 +cartoon/elephant/pic_450.jpg 2 +cartoon/elephant/pic_468.jpg 2 +cartoon/elephant/pic_459.jpg 2 +cartoon/elephant/pic_455.jpg 2 +cartoon/elephant/pic_457.jpg 2 +cartoon/elephant/pic_466.jpg 2 +cartoon/elephant/pic_465.jpg 2 +cartoon/elephant/pic_471.jpg 2 +cartoon/elephant/pic_469.jpg 2 +cartoon/elephant/pic_496.jpg 2 +cartoon/elephant/pic_495.jpg 2 +cartoon/elephant/pic_497.jpg 2 +cartoon/elephant/pic_498.jpg 2 +cartoon/elephant/pic_499.jpg 2 +cartoon/elephant/pic_502.jpg 2 +cartoon/elephant/pic_504.jpg 2 +cartoon/elephant/pic_501.jpg 2 +cartoon/elephant/pic_505.jpg 2 +cartoon/elephant/pic_245.jpg 2 +cartoon/elephant/pic_246.jpg 2 +cartoon/elephant/pic_253.jpg 2 +cartoon/elephant/pic_299.jpg 2 +cartoon/elephant/pic_278.jpg 2 +cartoon/elephant/pic_288.jpg 2 +cartoon/elephant/pic_304.jpg 2 +cartoon/elephant/pic_303.jpg 2 +cartoon/elephant/pic_266.jpg 2 +cartoon/elephant/pic_265.jpg 2 +cartoon/elephant/pic_256.jpg 2 +cartoon/elephant/pic_254.jpg 2 +cartoon/elephant/pic_255.jpg 2 +cartoon/elephant/pic_306.jpg 2 +cartoon/elephant/pic_293.jpg 2 +cartoon/elephant/pic_302.jpg 2 +cartoon/elephant/pic_301.jpg 2 +cartoon/elephant/pic_300.jpg 2 +cartoon/elephant/pic_138.jpg 2 +cartoon/elephant/pic_125.jpg 2 +cartoon/elephant/pic_112.jpg 2 +cartoon/elephant/pic_144.jpg 2 +cartoon/elephant/pic_101.jpg 2 +cartoon/elephant/pic_122.jpg 2 +cartoon/elephant/pic_120.jpg 2 +cartoon/elephant/pic_105.jpg 2 +cartoon/elephant/pic_189.jpg 2 +cartoon/elephant/pic_141.jpg 2 +cartoon/elephant/pic_143.jpg 2 +cartoon/elephant/pic_160.jpg 2 +cartoon/elephant/pic_113.jpg 2 +cartoon/elephant/pic_145.jpg 2 +cartoon/elephant/pic_109.jpg 2 +cartoon/elephant/pic_148.jpg 2 +cartoon/elephant/pic_128.jpg 2 +cartoon/elephant/pic_127.jpg 2 +cartoon/elephant/pic_150.jpg 2 +cartoon/elephant/pic_124.jpg 2 +cartoon/giraffe/pic_098.jpg 3 +cartoon/giraffe/pic_097.jpg 3 +cartoon/giraffe/pic_107.jpg 3 +cartoon/giraffe/pic_109.jpg 3 +cartoon/giraffe/pic_285.jpg 3 +cartoon/giraffe/pic_282.jpg 3 +cartoon/giraffe/pic_284.jpg 3 +cartoon/giraffe/pic_287.jpg 3 +cartoon/giraffe/pic_286.jpg 3 +cartoon/giraffe/pic_298.jpg 3 +cartoon/giraffe/pic_296.jpg 3 +cartoon/giraffe/pic_294.jpg 3 +cartoon/giraffe/pic_293.jpg 3 +cartoon/giraffe/pic_292.jpg 3 +cartoon/giraffe/pic_290.jpg 3 +cartoon/giraffe/pic_288.jpg 3 +cartoon/giraffe/pic_291.jpg 3 +cartoon/giraffe/pic_320.jpg 3 +cartoon/giraffe/pic_313.jpg 3 +cartoon/giraffe/pic_305.jpg 3 +cartoon/giraffe/pic_307.jpg 3 +cartoon/giraffe/pic_306.jpg 3 +cartoon/giraffe/pic_303.jpg 3 +cartoon/giraffe/pic_152.jpg 3 +cartoon/giraffe/pic_153.jpg 3 +cartoon/giraffe/pic_151.jpg 3 +cartoon/giraffe/pic_155.jpg 3 +cartoon/giraffe/pic_156.jpg 3 +cartoon/giraffe/pic_157.jpg 3 +cartoon/giraffe/pic_159.jpg 3 +cartoon/giraffe/pic_160.jpg 3 +cartoon/giraffe/pic_161.jpg 3 +cartoon/giraffe/pic_162.jpg 3 +cartoon/giraffe/pic_158.jpg 3 +cartoon/giraffe/pic_163.jpg 3 +cartoon/giraffe/pic_164.jpg 3 +cartoon/giraffe/pic_165.jpg 3 +cartoon/giraffe/pic_166.jpg 3 +cartoon/giraffe/pic_167.jpg 3 +cartoon/giraffe/pic_168.jpg 3 +cartoon/giraffe/pic_170.jpg 3 +cartoon/giraffe/pic_369.jpg 3 +cartoon/giraffe/pic_368.jpg 3 +cartoon/giraffe/pic_367.jpg 3 +cartoon/giraffe/pic_365.jpg 3 +cartoon/giraffe/pic_364.jpg 3 +cartoon/giraffe/pic_363.jpg 3 +cartoon/giraffe/pic_373.jpg 3 +cartoon/giraffe/pic_370.jpg 3 +cartoon/giraffe/pic_376.jpg 3 +cartoon/giraffe/pic_375.jpg 3 +cartoon/giraffe/pic_377.jpg 3 +cartoon/giraffe/pic_379.jpg 3 +cartoon/giraffe/pic_381.jpg 3 +cartoon/giraffe/pic_382.jpg 3 +cartoon/giraffe/pic_380.jpg 3 +cartoon/giraffe/pic_383.jpg 3 +cartoon/giraffe/pic_385.jpg 3 +cartoon/giraffe/pic_384.jpg 3 +cartoon/giraffe/pic_386.jpg 3 +cartoon/giraffe/pic_031.jpg 3 +cartoon/giraffe/pic_030.jpg 3 +cartoon/giraffe/pic_029.jpg 3 +cartoon/giraffe/pic_027.jpg 3 +cartoon/giraffe/pic_023.jpg 3 +cartoon/giraffe/pic_026.jpg 3 +cartoon/giraffe/pic_033.jpg 3 +cartoon/giraffe/pic_028.jpg 3 +cartoon/giraffe/pic_032.jpg 3 +cartoon/giraffe/pic_043.jpg 3 +cartoon/giraffe/pic_042.jpg 3 +cartoon/giraffe/pic_041.jpg 3 +cartoon/giraffe/pic_039.jpg 3 +cartoon/giraffe/pic_038.jpg 3 +cartoon/giraffe/pic_036.jpg 3 +cartoon/giraffe/pic_035.jpg 3 +cartoon/giraffe/pic_037.jpg 3 +cartoon/giraffe/pic_040.jpg 3 +cartoon/giraffe/pic_051.jpg 3 +cartoon/giraffe/pic_050.jpg 3 +cartoon/giraffe/pic_048.jpg 3 +cartoon/giraffe/pic_047.jpg 3 +cartoon/giraffe/pic_045.jpg 3 +cartoon/giraffe/pic_044.jpg 3 +cartoon/giraffe/pic_053.jpg 3 +cartoon/giraffe/pic_052.jpg 3 +cartoon/giraffe/pic_054.jpg 3 +cartoon/giraffe/pic_056.jpg 3 +cartoon/giraffe/pic_055.jpg 3 +cartoon/giraffe/pic_057.jpg 3 +cartoon/giraffe/pic_059.jpg 3 +cartoon/giraffe/pic_060.jpg 3 +cartoon/giraffe/pic_058.jpg 3 +cartoon/giraffe/pic_062.jpg 3 +cartoon/giraffe/pic_061.jpg 3 +cartoon/giraffe/pic_067.jpg 3 +cartoon/giraffe/pic_064.jpg 3 +cartoon/giraffe/pic_065.jpg 3 +cartoon/giraffe/pic_066.jpg 3 +cartoon/giraffe/pic_233.jpg 3 +cartoon/giraffe/pic_235.jpg 3 +cartoon/giraffe/pic_236.jpg 3 +cartoon/giraffe/pic_238.jpg 3 +cartoon/giraffe/pic_237.jpg 3 +cartoon/giraffe/pic_239.jpg 3 +cartoon/giraffe/pic_130.jpg 3 +cartoon/giraffe/pic_131.jpg 3 +cartoon/giraffe/pic_134.jpg 3 +cartoon/giraffe/pic_133.jpg 3 +cartoon/giraffe/pic_132.jpg 3 +cartoon/giraffe/pic_136.jpg 3 +cartoon/giraffe/pic_138.jpg 3 +cartoon/giraffe/pic_139.jpg 3 +cartoon/giraffe/pic_141.jpg 3 +cartoon/giraffe/pic_143.jpg 3 +cartoon/giraffe/pic_145.jpg 3 +cartoon/giraffe/pic_147.jpg 3 +cartoon/giraffe/pic_144.jpg 3 +cartoon/giraffe/pic_146.jpg 3 +cartoon/giraffe/pic_149.jpg 3 +cartoon/giraffe/pic_148.jpg 3 +cartoon/giraffe/pic_343.jpg 3 +cartoon/giraffe/pic_346.jpg 3 +cartoon/giraffe/pic_352.jpg 3 +cartoon/giraffe/pic_355.jpg 3 +cartoon/giraffe/pic_354.jpg 3 +cartoon/giraffe/pic_351.jpg 3 +cartoon/giraffe/pic_350.jpg 3 +cartoon/giraffe/pic_353.jpg 3 +cartoon/giraffe/pic_349.jpg 3 +cartoon/giraffe/pic_359.jpg 3 +cartoon/giraffe/pic_360.jpg 3 +cartoon/giraffe/pic_361.jpg 3 +cartoon/giraffe/pic_358.jpg 3 +cartoon/giraffe/pic_356.jpg 3 +cartoon/giraffe/pic_374.jpg 3 +cartoon/giraffe/pic_372.jpg 3 +cartoon/giraffe/pic_371.jpg 3 +cartoon/giraffe/pic_174.jpg 3 +cartoon/giraffe/pic_172.jpg 3 +cartoon/giraffe/pic_173.jpg 3 +cartoon/giraffe/pic_177.jpg 3 +cartoon/giraffe/pic_175.jpg 3 +cartoon/giraffe/pic_176.jpg 3 +cartoon/giraffe/pic_178.jpg 3 +cartoon/giraffe/pic_179.jpg 3 +cartoon/giraffe/pic_180.jpg 3 +cartoon/giraffe/pic_181.jpg 3 +cartoon/giraffe/pic_182.jpg 3 +cartoon/giraffe/pic_185.jpg 3 +cartoon/giraffe/pic_183.jpg 3 +cartoon/giraffe/pic_186.jpg 3 +cartoon/giraffe/pic_187.jpg 3 +cartoon/giraffe/pic_188.jpg 3 +cartoon/giraffe/pic_189.jpg 3 +cartoon/giraffe/pic_190.jpg 3 +cartoon/giraffe/pic_192.jpg 3 +cartoon/giraffe/pic_262.jpg 3 +cartoon/giraffe/pic_265.jpg 3 +cartoon/giraffe/pic_266.jpg 3 +cartoon/giraffe/pic_264.jpg 3 +cartoon/giraffe/pic_267.jpg 3 +cartoon/giraffe/pic_268.jpg 3 +cartoon/giraffe/pic_269.jpg 3 +cartoon/giraffe/pic_270.jpg 3 +cartoon/giraffe/pic_272.jpg 3 +cartoon/giraffe/pic_271.jpg 3 +cartoon/giraffe/pic_275.jpg 3 +cartoon/giraffe/pic_274.jpg 3 +cartoon/giraffe/pic_273.jpg 3 +cartoon/giraffe/pic_276.jpg 3 +cartoon/giraffe/pic_279.jpg 3 +cartoon/giraffe/pic_277.jpg 3 +cartoon/giraffe/pic_278.jpg 3 +cartoon/giraffe/pic_280.jpg 3 +cartoon/giraffe/pic_063.jpg 3 +cartoon/giraffe/pic_068.jpg 3 +cartoon/giraffe/pic_080.jpg 3 +cartoon/giraffe/pic_082.jpg 3 +cartoon/giraffe/pic_079.jpg 3 +cartoon/giraffe/pic_077.jpg 3 +cartoon/giraffe/pic_078.jpg 3 +cartoon/giraffe/pic_074.jpg 3 +cartoon/giraffe/pic_075.jpg 3 +cartoon/giraffe/pic_073.jpg 3 +cartoon/giraffe/pic_072.jpg 3 +cartoon/giraffe/pic_071.jpg 3 +cartoon/giraffe/pic_069.jpg 3 +cartoon/giraffe/pic_083.jpg 3 +cartoon/giraffe/pic_084.jpg 3 +cartoon/giraffe/pic_076.jpg 3 +cartoon/giraffe/pic_089.jpg 3 +cartoon/giraffe/pic_088.jpg 3 +cartoon/giraffe/pic_194.jpg 3 +cartoon/giraffe/pic_193.jpg 3 +cartoon/giraffe/pic_195.jpg 3 +cartoon/giraffe/pic_196.jpg 3 +cartoon/giraffe/pic_197.jpg 3 +cartoon/giraffe/pic_198.jpg 3 +cartoon/giraffe/pic_199.jpg 3 +cartoon/giraffe/pic_200.jpg 3 +cartoon/giraffe/pic_201.jpg 3 +cartoon/giraffe/pic_202.jpg 3 +cartoon/giraffe/pic_203.jpg 3 +cartoon/giraffe/pic_204.jpg 3 +cartoon/giraffe/pic_205.jpg 3 +cartoon/giraffe/pic_206.jpg 3 +cartoon/giraffe/pic_209.jpg 3 +cartoon/giraffe/pic_208.jpg 3 +cartoon/giraffe/pic_210.jpg 3 +cartoon/giraffe/pic_212.jpg 3 +cartoon/giraffe/pic_211.jpg 3 +cartoon/giraffe/pic_216.jpg 3 +cartoon/giraffe/pic_102.jpg 3 +cartoon/giraffe/pic_105.jpg 3 +cartoon/giraffe/pic_121.jpg 3 +cartoon/giraffe/pic_124.jpg 3 +cartoon/giraffe/pic_122.jpg 3 +cartoon/giraffe/pic_119.jpg 3 +cartoon/giraffe/pic_118.jpg 3 +cartoon/giraffe/pic_117.jpg 3 +cartoon/giraffe/pic_115.jpg 3 +cartoon/giraffe/pic_116.jpg 3 +cartoon/giraffe/pic_114.jpg 3 +cartoon/giraffe/pic_112.jpg 3 +cartoon/giraffe/pic_111.jpg 3 +cartoon/giraffe/pic_123.jpg 3 +cartoon/giraffe/pic_113.jpg 3 +cartoon/giraffe/pic_120.jpg 3 +cartoon/giraffe/pic_127.jpg 3 +cartoon/giraffe/pic_126.jpg 3 +cartoon/giraffe/pic_125.jpg 3 +cartoon/giraffe/pic_129.jpg 3 +cartoon/giraffe/pic_128.jpg 3 +cartoon/giraffe/pic_001.jpg 3 +cartoon/giraffe/pic_002.jpg 3 +cartoon/giraffe/pic_003.jpg 3 +cartoon/giraffe/pic_004.jpg 3 +cartoon/giraffe/pic_215.jpg 3 +cartoon/giraffe/pic_214.jpg 3 +cartoon/giraffe/pic_213.jpg 3 +cartoon/giraffe/pic_218.jpg 3 +cartoon/giraffe/pic_219.jpg 3 +cartoon/giraffe/pic_217.jpg 3 +cartoon/giraffe/pic_220.jpg 3 +cartoon/giraffe/pic_221.jpg 3 +cartoon/giraffe/pic_222.jpg 3 +cartoon/giraffe/pic_224.jpg 3 +cartoon/giraffe/pic_225.jpg 3 +cartoon/giraffe/pic_226.jpg 3 +cartoon/giraffe/pic_227.jpg 3 +cartoon/giraffe/pic_228.jpg 3 +cartoon/giraffe/pic_229.jpg 3 +cartoon/giraffe/pic_230.jpg 3 +cartoon/giraffe/pic_231.jpg 3 +cartoon/giraffe/pic_232.jpg 3 +cartoon/giraffe/pic_344.jpg 3 +cartoon/giraffe/pic_345.jpg 3 +cartoon/giraffe/pic_342.jpg 3 +cartoon/giraffe/pic_334.jpg 3 +cartoon/giraffe/pic_335.jpg 3 +cartoon/giraffe/pic_327.jpg 3 +cartoon/giraffe/pic_330.jpg 3 +cartoon/giraffe/pic_333.jpg 3 +cartoon/giraffe/pic_328.jpg 3 +cartoon/giraffe/pic_331.jpg 3 +cartoon/giraffe/pic_326.jpg 3 +cartoon/giraffe/pic_324.jpg 3 +cartoon/giraffe/pic_323.jpg 3 +cartoon/giraffe/pic_347.jpg 3 +cartoon/giraffe/pic_341.jpg 3 +cartoon/giraffe/pic_336.jpg 3 +cartoon/giraffe/pic_339.jpg 3 +cartoon/giraffe/pic_337.jpg 3 +cartoon/giraffe/pic_304.jpg 3 +cartoon/giraffe/pic_302.jpg 3 +cartoon/giraffe/pic_297.jpg 3 +cartoon/giraffe/pic_295.jpg 3 +cartoon/giraffe/pic_299.jpg 3 +cartoon/giraffe/pic_316.jpg 3 +cartoon/giraffe/pic_312.jpg 3 +cartoon/giraffe/pic_318.jpg 3 +cartoon/giraffe/pic_319.jpg 3 +cartoon/giraffe/pic_308.jpg 3 +cartoon/giraffe/pic_310.jpg 3 +cartoon/giraffe/pic_309.jpg 3 +cartoon/giraffe/pic_301.jpg 3 +cartoon/giraffe/pic_311.jpg 3 +cartoon/giraffe/pic_322.jpg 3 +cartoon/giraffe/pic_321.jpg 3 +cartoon/giraffe/pic_300.jpg 3 +cartoon/giraffe/pic_317.jpg 3 +cartoon/giraffe/pic_340.jpg 3 +cartoon/giraffe/pic_242.jpg 3 +cartoon/giraffe/pic_241.jpg 3 +cartoon/giraffe/pic_243.jpg 3 +cartoon/giraffe/pic_244.jpg 3 +cartoon/giraffe/pic_245.jpg 3 +cartoon/giraffe/pic_246.jpg 3 +cartoon/giraffe/pic_247.jpg 3 +cartoon/giraffe/pic_249.jpg 3 +cartoon/giraffe/pic_248.jpg 3 +cartoon/giraffe/pic_251.jpg 3 +cartoon/giraffe/pic_252.jpg 3 +cartoon/giraffe/pic_253.jpg 3 +cartoon/giraffe/pic_254.jpg 3 +cartoon/giraffe/pic_256.jpg 3 +cartoon/giraffe/pic_257.jpg 3 +cartoon/giraffe/pic_259.jpg 3 +cartoon/giraffe/pic_260.jpg 3 +cartoon/giraffe/pic_261.jpg 3 +cartoon/guitar/pic_019.jpg 4 +cartoon/guitar/pic_022.jpg 4 +cartoon/guitar/pic_028.jpg 4 +cartoon/guitar/pic_025.jpg 4 +cartoon/guitar/pic_069.jpg 4 +cartoon/guitar/pic_067.jpg 4 +cartoon/guitar/pic_068.jpg 4 +cartoon/guitar/pic_063.jpg 4 +cartoon/guitar/pic_066.jpg 4 +cartoon/guitar/pic_064.jpg 4 +cartoon/guitar/pic_071.jpg 4 +cartoon/guitar/pic_070.jpg 4 +cartoon/guitar/pic_076.jpg 4 +cartoon/guitar/pic_074.jpg 4 +cartoon/guitar/pic_077.jpg 4 +cartoon/guitar/pic_075.jpg 4 +cartoon/guitar/pic_079.jpg 4 +cartoon/guitar/pic_078.jpg 4 +cartoon/guitar/pic_112.jpg 4 +cartoon/guitar/pic_135.jpg 4 +cartoon/guitar/pic_151.jpg 4 +cartoon/guitar/pic_133.jpg 4 +cartoon/guitar/pic_128.jpg 4 +cartoon/guitar/pic_122.jpg 4 +cartoon/guitar/pic_024.jpg 4 +cartoon/guitar/pic_023.jpg 4 +cartoon/guitar/pic_027.jpg 4 +cartoon/guitar/pic_034.jpg 4 +cartoon/guitar/pic_032.jpg 4 +cartoon/guitar/pic_031.jpg 4 +cartoon/guitar/pic_030.jpg 4 +cartoon/guitar/pic_029.jpg 4 +cartoon/guitar/pic_037.jpg 4 +cartoon/guitar/pic_036.jpg 4 +cartoon/guitar/pic_038.jpg 4 +cartoon/guitar/pic_040.jpg 4 +cartoon/guitar/pic_048.jpg 4 +cartoon/guitar/pic_045.jpg 4 +cartoon/guitar/pic_044.jpg 4 +cartoon/guitar/pic_043.jpg 4 +cartoon/guitar/pic_042.jpg 4 +cartoon/guitar/pic_021.jpg 4 +cartoon/guitar/pic_018.jpg 4 +cartoon/guitar/pic_039.jpg 4 +cartoon/guitar/pic_026.jpg 4 +cartoon/guitar/pic_104.jpg 4 +cartoon/guitar/pic_098.jpg 4 +cartoon/guitar/pic_146.jpg 4 +cartoon/guitar/pic_131.jpg 4 +cartoon/guitar/pic_106.jpg 4 +cartoon/guitar/pic_124.jpg 4 +cartoon/guitar/pic_137.jpg 4 +cartoon/guitar/pic_092.jpg 4 +cartoon/guitar/pic_096.jpg 4 +cartoon/guitar/pic_086.jpg 4 +cartoon/guitar/pic_145.jpg 4 +cartoon/guitar/pic_123.jpg 4 +cartoon/guitar/pic_111.jpg 4 +cartoon/guitar/pic_116.jpg 4 +cartoon/guitar/pic_150.jpg 4 +cartoon/guitar/pic_113.jpg 4 +cartoon/guitar/pic_107.jpg 4 +cartoon/guitar/pic_103.jpg 4 +cartoon/guitar/pic_097.jpg 4 +cartoon/guitar/pic_090.jpg 4 +cartoon/guitar/pic_088.jpg 4 +cartoon/guitar/pic_085.jpg 4 +cartoon/guitar/pic_083.jpg 4 +cartoon/guitar/pic_084.jpg 4 +cartoon/guitar/pic_082.jpg 4 +cartoon/guitar/pic_081.jpg 4 +cartoon/guitar/pic_080.jpg 4 +cartoon/guitar/pic_139.jpg 4 +cartoon/guitar/pic_140.jpg 4 +cartoon/guitar/pic_125.jpg 4 +cartoon/guitar/pic_117.jpg 4 +cartoon/guitar/pic_033.jpg 4 +cartoon/guitar/pic_035.jpg 4 +cartoon/guitar/pic_047.jpg 4 +cartoon/guitar/pic_046.jpg 4 +cartoon/guitar/pic_049.jpg 4 +cartoon/guitar/pic_052.jpg 4 +cartoon/guitar/pic_051.jpg 4 +cartoon/guitar/pic_053.jpg 4 +cartoon/guitar/pic_050.jpg 4 +cartoon/guitar/pic_054.jpg 4 +cartoon/guitar/pic_056.jpg 4 +cartoon/guitar/pic_055.jpg 4 +cartoon/guitar/pic_057.jpg 4 +cartoon/guitar/pic_060.jpg 4 +cartoon/guitar/pic_058.jpg 4 +cartoon/guitar/pic_059.jpg 4 +cartoon/guitar/pic_061.jpg 4 +cartoon/guitar/pic_065.jpg 4 +cartoon/guitar/pic_062.jpg 4 +cartoon/guitar/pic_073.jpg 4 +cartoon/guitar/pic_105.jpg 4 +cartoon/guitar/pic_136.jpg 4 +cartoon/guitar/pic_129.jpg 4 +cartoon/guitar/pic_110.jpg 4 +cartoon/guitar/pic_142.jpg 4 +cartoon/guitar/pic_089.jpg 4 +cartoon/guitar/pic_127.jpg 4 +cartoon/guitar/pic_148.jpg 4 +cartoon/guitar/pic_093.jpg 4 +cartoon/guitar/pic_100.jpg 4 +cartoon/guitar/pic_144.jpg 4 +cartoon/guitar/pic_149.jpg 4 +cartoon/guitar/pic_119.jpg 4 +cartoon/guitar/pic_121.jpg 4 +cartoon/guitar/pic_130.jpg 4 +cartoon/guitar/pic_094.jpg 4 +cartoon/guitar/pic_147.jpg 4 +cartoon/guitar/pic_099.jpg 4 +cartoon/guitar/pic_101.jpg 4 +cartoon/guitar/pic_132.jpg 4 +cartoon/guitar/pic_152.jpg 4 +cartoon/guitar/pic_134.jpg 4 +cartoon/guitar/pic_118.jpg 4 +cartoon/guitar/pic_001.jpg 4 +cartoon/guitar/pic_002.jpg 4 +cartoon/horse/pic_153.jpg 5 +cartoon/horse/pic_158.jpg 5 +cartoon/horse/pic_157.jpg 5 +cartoon/horse/pic_010.jpg 5 +cartoon/horse/pic_011.jpg 5 +cartoon/horse/pic_012.jpg 5 +cartoon/horse/pic_013.jpg 5 +cartoon/horse/pic_014.jpg 5 +cartoon/horse/pic_015.jpg 5 +cartoon/horse/pic_016.jpg 5 +cartoon/horse/pic_017.jpg 5 +cartoon/horse/pic_018.jpg 5 +cartoon/horse/pic_019.jpg 5 +cartoon/horse/pic_020.jpg 5 +cartoon/horse/pic_022.jpg 5 +cartoon/horse/pic_021.jpg 5 +cartoon/horse/pic_023.jpg 5 +cartoon/horse/pic_024.jpg 5 +cartoon/horse/pic_025.jpg 5 +cartoon/horse/pic_026.jpg 5 +cartoon/horse/pic_027.jpg 5 +cartoon/horse/pic_028.jpg 5 +cartoon/horse/pic_029.jpg 5 +cartoon/horse/pic_030.jpg 5 +cartoon/horse/pic_267.jpg 5 +cartoon/horse/pic_266.jpg 5 +cartoon/horse/pic_271.jpg 5 +cartoon/horse/pic_270.jpg 5 +cartoon/horse/pic_261.jpg 5 +cartoon/horse/pic_273.jpg 5 +cartoon/horse/pic_272.jpg 5 +cartoon/horse/pic_274.jpg 5 +cartoon/horse/pic_275.jpg 5 +cartoon/horse/pic_277.jpg 5 +cartoon/horse/pic_276.jpg 5 +cartoon/horse/pic_278.jpg 5 +cartoon/horse/pic_279.jpg 5 +cartoon/horse/pic_283.jpg 5 +cartoon/horse/pic_284.jpg 5 +cartoon/horse/pic_287.jpg 5 +cartoon/horse/pic_286.jpg 5 +cartoon/horse/pic_288.jpg 5 +cartoon/horse/pic_289.jpg 5 +cartoon/horse/pic_062.jpg 5 +cartoon/horse/pic_067.jpg 5 +cartoon/horse/pic_064.jpg 5 +cartoon/horse/pic_059.jpg 5 +cartoon/horse/pic_057.jpg 5 +cartoon/horse/pic_056.jpg 5 +cartoon/horse/pic_031.jpg 5 +cartoon/horse/pic_032.jpg 5 +cartoon/horse/pic_033.jpg 5 +cartoon/horse/pic_307.jpg 5 +cartoon/horse/pic_309.jpg 5 +cartoon/horse/pic_299.jpg 5 +cartoon/horse/pic_311.jpg 5 +cartoon/horse/pic_312.jpg 5 +cartoon/horse/pic_313.jpg 5 +cartoon/horse/pic_314.jpg 5 +cartoon/horse/pic_315.jpg 5 +cartoon/horse/pic_316.jpg 5 +cartoon/horse/pic_319.jpg 5 +cartoon/horse/pic_310.jpg 5 +cartoon/horse/pic_323.jpg 5 +cartoon/horse/pic_322.jpg 5 +cartoon/horse/pic_320.jpg 5 +cartoon/horse/pic_328.jpg 5 +cartoon/horse/pic_327.jpg 5 +cartoon/horse/pic_330.jpg 5 +cartoon/horse/pic_089.jpg 5 +cartoon/horse/pic_118.jpg 5 +cartoon/horse/pic_114.jpg 5 +cartoon/horse/pic_113.jpg 5 +cartoon/horse/pic_112.jpg 5 +cartoon/horse/pic_103.jpg 5 +cartoon/horse/pic_105.jpg 5 +cartoon/horse/pic_104.jpg 5 +cartoon/horse/pic_100.jpg 5 +cartoon/horse/pic_101.jpg 5 +cartoon/horse/pic_119.jpg 5 +cartoon/horse/pic_115.jpg 5 +cartoon/horse/pic_110.jpg 5 +cartoon/horse/pic_126.jpg 5 +cartoon/horse/pic_106.jpg 5 +cartoon/horse/pic_120.jpg 5 +cartoon/horse/pic_054.jpg 5 +cartoon/horse/pic_055.jpg 5 +cartoon/horse/pic_053.jpg 5 +cartoon/horse/pic_052.jpg 5 +cartoon/horse/pic_051.jpg 5 +cartoon/horse/pic_050.jpg 5 +cartoon/horse/pic_049.jpg 5 +cartoon/horse/pic_076.jpg 5 +cartoon/horse/pic_066.jpg 5 +cartoon/horse/pic_081.jpg 5 +cartoon/horse/pic_079.jpg 5 +cartoon/horse/pic_060.jpg 5 +cartoon/horse/pic_058.jpg 5 +cartoon/horse/pic_069.jpg 5 +cartoon/horse/pic_074.jpg 5 +cartoon/horse/pic_065.jpg 5 +cartoon/horse/pic_075.jpg 5 +cartoon/horse/pic_078.jpg 5 +cartoon/horse/pic_070.jpg 5 +cartoon/horse/pic_072.jpg 5 +cartoon/horse/pic_291.jpg 5 +cartoon/horse/pic_282.jpg 5 +cartoon/horse/pic_293.jpg 5 +cartoon/horse/pic_294.jpg 5 +cartoon/horse/pic_295.jpg 5 +cartoon/horse/pic_297.jpg 5 +cartoon/horse/pic_268.jpg 5 +cartoon/horse/pic_296.jpg 5 +cartoon/horse/pic_298.jpg 5 +cartoon/horse/pic_300.jpg 5 +cartoon/horse/pic_302.jpg 5 +cartoon/horse/pic_280.jpg 5 +cartoon/horse/pic_304.jpg 5 +cartoon/horse/pic_303.jpg 5 +cartoon/horse/pic_305.jpg 5 +cartoon/horse/pic_308.jpg 5 +cartoon/horse/pic_183.jpg 5 +cartoon/horse/pic_184.jpg 5 +cartoon/horse/pic_185.jpg 5 +cartoon/horse/pic_188.jpg 5 +cartoon/horse/pic_186.jpg 5 +cartoon/horse/pic_187.jpg 5 +cartoon/horse/pic_189.jpg 5 +cartoon/horse/pic_178.jpg 5 +cartoon/horse/pic_191.jpg 5 +cartoon/horse/pic_193.jpg 5 +cartoon/horse/pic_190.jpg 5 +cartoon/horse/pic_200.jpg 5 +cartoon/horse/pic_196.jpg 5 +cartoon/horse/pic_195.jpg 5 +cartoon/horse/pic_201.jpg 5 +cartoon/horse/pic_198.jpg 5 +cartoon/horse/pic_204.jpg 5 +cartoon/horse/pic_245.jpg 5 +cartoon/horse/pic_250.jpg 5 +cartoon/horse/pic_252.jpg 5 +cartoon/horse/pic_255.jpg 5 +cartoon/horse/pic_254.jpg 5 +cartoon/horse/pic_235.jpg 5 +cartoon/horse/pic_256.jpg 5 +cartoon/horse/pic_258.jpg 5 +cartoon/horse/pic_257.jpg 5 +cartoon/horse/pic_253.jpg 5 +cartoon/horse/pic_240.jpg 5 +cartoon/horse/pic_243.jpg 5 +cartoon/horse/pic_260.jpg 5 +cartoon/horse/pic_246.jpg 5 +cartoon/horse/pic_262.jpg 5 +cartoon/horse/pic_251.jpg 5 +cartoon/horse/pic_264.jpg 5 +cartoon/horse/pic_263.jpg 5 +cartoon/horse/pic_265.jpg 5 +cartoon/horse/pic_259.jpg 5 +cartoon/horse/pic_269.jpg 5 +cartoon/horse/pic_001.jpg 5 +cartoon/horse/pic_002.jpg 5 +cartoon/horse/pic_003.jpg 5 +cartoon/horse/pic_004.jpg 5 +cartoon/horse/pic_005.jpg 5 +cartoon/horse/pic_006.jpg 5 +cartoon/horse/pic_007.jpg 5 +cartoon/horse/pic_008.jpg 5 +cartoon/horse/pic_009.jpg 5 +cartoon/horse/pic_116.jpg 5 +cartoon/horse/pic_108.jpg 5 +cartoon/horse/pic_111.jpg 5 +cartoon/horse/pic_128.jpg 5 +cartoon/horse/pic_124.jpg 5 +cartoon/horse/pic_130.jpg 5 +cartoon/horse/pic_131.jpg 5 +cartoon/horse/pic_129.jpg 5 +cartoon/horse/pic_125.jpg 5 +cartoon/horse/pic_121.jpg 5 +cartoon/horse/pic_127.jpg 5 +cartoon/horse/pic_123.jpg 5 +cartoon/horse/pic_143.jpg 5 +cartoon/horse/pic_135.jpg 5 +cartoon/horse/pic_134.jpg 5 +cartoon/horse/pic_140.jpg 5 +cartoon/horse/pic_145.jpg 5 +cartoon/horse/pic_146.jpg 5 +cartoon/horse/pic_142.jpg 5 +cartoon/horse/pic_137.jpg 5 +cartoon/horse/pic_350.jpg 5 +cartoon/horse/pic_351.jpg 5 +cartoon/horse/pic_352.jpg 5 +cartoon/horse/pic_353.jpg 5 +cartoon/horse/pic_354.jpg 5 +cartoon/horse/pic_355.jpg 5 +cartoon/horse/pic_345.jpg 5 +cartoon/horse/pic_357.jpg 5 +cartoon/horse/pic_359.jpg 5 +cartoon/horse/pic_358.jpg 5 +cartoon/horse/pic_361.jpg 5 +cartoon/horse/pic_362.jpg 5 +cartoon/horse/pic_364.jpg 5 +cartoon/horse/pic_356.jpg 5 +cartoon/horse/pic_363.jpg 5 +cartoon/horse/pic_160.jpg 5 +cartoon/horse/pic_173.jpg 5 +cartoon/horse/pic_172.jpg 5 +cartoon/horse/pic_169.jpg 5 +cartoon/horse/pic_167.jpg 5 +cartoon/horse/pic_166.jpg 5 +cartoon/horse/pic_164.jpg 5 +cartoon/horse/pic_163.jpg 5 +cartoon/horse/pic_152.jpg 5 +cartoon/horse/pic_174.jpg 5 +cartoon/horse/pic_171.jpg 5 +cartoon/horse/pic_177.jpg 5 +cartoon/horse/pic_176.jpg 5 +cartoon/horse/pic_181.jpg 5 +cartoon/horse/pic_180.jpg 5 +cartoon/horse/pic_179.jpg 5 +cartoon/horse/pic_084.jpg 5 +cartoon/horse/pic_083.jpg 5 +cartoon/horse/pic_071.jpg 5 +cartoon/horse/pic_096.jpg 5 +cartoon/horse/pic_094.jpg 5 +cartoon/horse/pic_098.jpg 5 +cartoon/horse/pic_095.jpg 5 +cartoon/horse/pic_093.jpg 5 +cartoon/horse/pic_092.jpg 5 +cartoon/horse/pic_091.jpg 5 +cartoon/horse/pic_090.jpg 5 +cartoon/horse/pic_088.jpg 5 +cartoon/horse/pic_086.jpg 5 +cartoon/horse/pic_097.jpg 5 +cartoon/horse/pic_087.jpg 5 +cartoon/horse/pic_203.jpg 5 +cartoon/horse/pic_205.jpg 5 +cartoon/horse/pic_209.jpg 5 +cartoon/horse/pic_212.jpg 5 +cartoon/horse/pic_213.jpg 5 +cartoon/horse/pic_192.jpg 5 +cartoon/horse/pic_211.jpg 5 +cartoon/horse/pic_214.jpg 5 +cartoon/horse/pic_218.jpg 5 +cartoon/horse/pic_215.jpg 5 +cartoon/horse/pic_217.jpg 5 +cartoon/horse/pic_220.jpg 5 +cartoon/horse/pic_219.jpg 5 +cartoon/horse/pic_221.jpg 5 +cartoon/horse/pic_223.jpg 5 +cartoon/horse/pic_224.jpg 5 +cartoon/horse/pic_208.jpg 5 +cartoon/horse/pic_035.jpg 5 +cartoon/horse/pic_034.jpg 5 +cartoon/horse/pic_037.jpg 5 +cartoon/horse/pic_036.jpg 5 +cartoon/horse/pic_044.jpg 5 +cartoon/horse/pic_047.jpg 5 +cartoon/horse/pic_045.jpg 5 +cartoon/horse/pic_043.jpg 5 +cartoon/horse/pic_042.jpg 5 +cartoon/horse/pic_040.jpg 5 +cartoon/horse/pic_041.jpg 5 +cartoon/horse/pic_038.jpg 5 +cartoon/horse/pic_039.jpg 5 +cartoon/horse/pic_048.jpg 5 +cartoon/horse/pic_046.jpg 5 +cartoon/horse/pic_061.jpg 5 +cartoon/horse/pic_073.jpg 5 +cartoon/horse/pic_077.jpg 5 +cartoon/horse/pic_080.jpg 5 +cartoon/horse/pic_082.jpg 5 +cartoon/horse/pic_225.jpg 5 +cartoon/horse/pic_228.jpg 5 +cartoon/horse/pic_207.jpg 5 +cartoon/horse/pic_227.jpg 5 +cartoon/horse/pic_226.jpg 5 +cartoon/horse/pic_231.jpg 5 +cartoon/horse/pic_232.jpg 5 +cartoon/horse/pic_234.jpg 5 +cartoon/horse/pic_236.jpg 5 +cartoon/horse/pic_237.jpg 5 +cartoon/horse/pic_239.jpg 5 +cartoon/horse/pic_238.jpg 5 +cartoon/horse/pic_229.jpg 5 +cartoon/horse/pic_241.jpg 5 +cartoon/horse/pic_242.jpg 5 +cartoon/horse/pic_244.jpg 5 +cartoon/horse/pic_233.jpg 5 +cartoon/horse/pic_249.jpg 5 +cartoon/horse/pic_248.jpg 5 +cartoon/horse/pic_247.jpg 5 +cartoon/house/pic_071.jpg 6 +cartoon/house/pic_072.jpg 6 +cartoon/house/pic_074.jpg 6 +cartoon/house/pic_077.jpg 6 +cartoon/house/pic_081.jpg 6 +cartoon/house/pic_088.jpg 6 +cartoon/house/pic_082.jpg 6 +cartoon/house/pic_080.jpg 6 +cartoon/house/pic_090.jpg 6 +cartoon/house/pic_100.jpg 6 +cartoon/house/pic_084.jpg 6 +cartoon/house/pic_085.jpg 6 +cartoon/house/pic_083.jpg 6 +cartoon/house/pic_087.jpg 6 +cartoon/house/pic_094.jpg 6 +cartoon/house/pic_157.jpg 6 +cartoon/house/pic_169.jpg 6 +cartoon/house/pic_172.jpg 6 +cartoon/house/pic_173.jpg 6 +cartoon/house/pic_171.jpg 6 +cartoon/house/pic_176.jpg 6 +cartoon/house/pic_180.jpg 6 +cartoon/house/pic_182.jpg 6 +cartoon/house/pic_185.jpg 6 +cartoon/house/pic_184.jpg 6 +cartoon/house/pic_187.jpg 6 +cartoon/house/pic_188.jpg 6 +cartoon/house/pic_189.jpg 6 +cartoon/house/pic_191.jpg 6 +cartoon/house/pic_174.jpg 6 +cartoon/house/pic_179.jpg 6 +cartoon/house/pic_237.jpg 6 +cartoon/house/pic_258.jpg 6 +cartoon/house/pic_260.jpg 6 +cartoon/house/pic_242.jpg 6 +cartoon/house/pic_262.jpg 6 +cartoon/house/pic_263.jpg 6 +cartoon/house/pic_249.jpg 6 +cartoon/house/pic_253.jpg 6 +cartoon/house/pic_257.jpg 6 +cartoon/house/pic_265.jpg 6 +cartoon/house/pic_267.jpg 6 +cartoon/house/pic_268.jpg 6 +cartoon/house/pic_269.jpg 6 +cartoon/house/pic_272.jpg 6 +cartoon/house/pic_264.jpg 6 +cartoon/house/pic_274.jpg 6 +cartoon/house/pic_270.jpg 6 +cartoon/house/pic_177.jpg 6 +cartoon/house/pic_192.jpg 6 +cartoon/house/pic_193.jpg 6 +cartoon/house/pic_178.jpg 6 +cartoon/house/pic_181.jpg 6 +cartoon/house/pic_194.jpg 6 +cartoon/house/pic_196.jpg 6 +cartoon/house/pic_197.jpg 6 +cartoon/house/pic_198.jpg 6 +cartoon/house/pic_199.jpg 6 +cartoon/house/pic_200.jpg 6 +cartoon/house/pic_201.jpg 6 +cartoon/house/pic_202.jpg 6 +cartoon/house/pic_203.jpg 6 +cartoon/house/pic_205.jpg 6 +cartoon/house/pic_195.jpg 6 +cartoon/house/pic_207.jpg 6 +cartoon/house/pic_206.jpg 6 +cartoon/house/pic_204.jpg 6 +cartoon/house/pic_209.jpg 6 +cartoon/house/pic_234.jpg 6 +cartoon/house/pic_239.jpg 6 +cartoon/house/pic_241.jpg 6 +cartoon/house/pic_240.jpg 6 +cartoon/house/pic_224.jpg 6 +cartoon/house/pic_243.jpg 6 +cartoon/house/pic_246.jpg 6 +cartoon/house/pic_245.jpg 6 +cartoon/house/pic_244.jpg 6 +cartoon/house/pic_250.jpg 6 +cartoon/house/pic_230.jpg 6 +cartoon/house/pic_238.jpg 6 +cartoon/house/pic_252.jpg 6 +cartoon/house/pic_254.jpg 6 +cartoon/house/pic_255.jpg 6 +cartoon/house/pic_256.jpg 6 +cartoon/house/pic_008.jpg 6 +cartoon/house/pic_009.jpg 6 +cartoon/house/pic_010.jpg 6 +cartoon/house/pic_011.jpg 6 +cartoon/house/pic_012.jpg 6 +cartoon/house/pic_013.jpg 6 +cartoon/house/pic_014.jpg 6 +cartoon/house/pic_016.jpg 6 +cartoon/house/pic_017.jpg 6 +cartoon/house/pic_020.jpg 6 +cartoon/house/pic_022.jpg 6 +cartoon/house/pic_026.jpg 6 +cartoon/house/pic_024.jpg 6 +cartoon/house/pic_027.jpg 6 +cartoon/house/pic_028.jpg 6 +cartoon/house/pic_032.jpg 6 +cartoon/house/pic_029.jpg 6 +cartoon/house/pic_001.jpg 6 +cartoon/house/pic_002.jpg 6 +cartoon/house/pic_003.jpg 6 +cartoon/house/pic_004.jpg 6 +cartoon/house/pic_005.jpg 6 +cartoon/house/pic_006.jpg 6 +cartoon/house/pic_007.jpg 6 +cartoon/house/pic_158.jpg 6 +cartoon/house/pic_160.jpg 6 +cartoon/house/pic_161.jpg 6 +cartoon/house/pic_162.jpg 6 +cartoon/house/pic_151.jpg 6 +cartoon/house/pic_164.jpg 6 +cartoon/house/pic_165.jpg 6 +cartoon/house/pic_156.jpg 6 +cartoon/house/pic_166.jpg 6 +cartoon/house/pic_167.jpg 6 +cartoon/house/pic_168.jpg 6 +cartoon/house/pic_163.jpg 6 +cartoon/house/pic_318.jpg 6 +cartoon/house/pic_331.jpg 6 +cartoon/house/pic_333.jpg 6 +cartoon/house/pic_334.jpg 6 +cartoon/house/pic_337.jpg 6 +cartoon/house/pic_335.jpg 6 +cartoon/house/pic_338.jpg 6 +cartoon/house/pic_341.jpg 6 +cartoon/house/pic_343.jpg 6 +cartoon/house/pic_344.jpg 6 +cartoon/house/pic_330.jpg 6 +cartoon/house/pic_346.jpg 6 +cartoon/house/pic_348.jpg 6 +cartoon/house/pic_340.jpg 6 +cartoon/house/pic_349.jpg 6 +cartoon/house/pic_347.jpg 6 +cartoon/house/pic_336.jpg 6 +cartoon/house/pic_355.jpg 6 +cartoon/house/pic_356.jpg 6 +cartoon/house/pic_357.jpg 6 +cartoon/house/pic_358.jpg 6 +cartoon/house/pic_360.jpg 6 +cartoon/house/pic_345.jpg 6 +cartoon/house/pic_354.jpg 6 +cartoon/house/pic_353.jpg 6 +cartoon/house/pic_359.jpg 6 +cartoon/house/pic_212.jpg 6 +cartoon/house/pic_211.jpg 6 +cartoon/house/pic_221.jpg 6 +cartoon/house/pic_219.jpg 6 +cartoon/house/pic_218.jpg 6 +cartoon/house/pic_215.jpg 6 +cartoon/house/pic_217.jpg 6 +cartoon/house/pic_220.jpg 6 +cartoon/house/pic_222.jpg 6 +cartoon/house/pic_223.jpg 6 +cartoon/house/pic_216.jpg 6 +cartoon/house/pic_208.jpg 6 +cartoon/house/pic_225.jpg 6 +cartoon/house/pic_226.jpg 6 +cartoon/house/pic_214.jpg 6 +cartoon/house/pic_231.jpg 6 +cartoon/house/pic_233.jpg 6 +cartoon/house/pic_228.jpg 6 +cartoon/house/pic_235.jpg 6 +cartoon/house/pic_273.jpg 6 +cartoon/house/pic_279.jpg 6 +cartoon/house/pic_278.jpg 6 +cartoon/house/pic_283.jpg 6 +cartoon/house/pic_280.jpg 6 +cartoon/house/pic_266.jpg 6 +cartoon/house/pic_281.jpg 6 +cartoon/house/pic_286.jpg 6 +cartoon/house/pic_276.jpg 6 +cartoon/house/pic_277.jpg 6 +cartoon/house/pic_288.jpg 6 +cartoon/house/pic_289.jpg 6 +cartoon/house/pic_282.jpg 6 +cartoon/house/pic_290.jpg 6 +cartoon/house/pic_292.jpg 6 +cartoon/house/pic_285.jpg 6 +cartoon/house/pic_295.jpg 6 +cartoon/house/pic_047.jpg 6 +cartoon/house/pic_049.jpg 6 +cartoon/house/pic_048.jpg 6 +cartoon/house/pic_050.jpg 6 +cartoon/house/pic_053.jpg 6 +cartoon/house/pic_056.jpg 6 +cartoon/house/pic_054.jpg 6 +cartoon/house/pic_059.jpg 6 +cartoon/house/pic_057.jpg 6 +cartoon/house/pic_067.jpg 6 +cartoon/house/pic_062.jpg 6 +cartoon/house/pic_060.jpg 6 +cartoon/house/pic_063.jpg 6 +cartoon/house/pic_066.jpg 6 +cartoon/house/pic_064.jpg 6 +cartoon/house/pic_065.jpg 6 +cartoon/house/pic_284.jpg 6 +cartoon/house/pic_297.jpg 6 +cartoon/house/pic_296.jpg 6 +cartoon/house/pic_298.jpg 6 +cartoon/house/pic_301.jpg 6 +cartoon/house/pic_302.jpg 6 +cartoon/house/pic_304.jpg 6 +cartoon/house/pic_305.jpg 6 +cartoon/house/pic_306.jpg 6 +cartoon/house/pic_291.jpg 6 +cartoon/house/pic_309.jpg 6 +cartoon/house/pic_308.jpg 6 +cartoon/house/pic_310.jpg 6 +cartoon/house/pic_299.jpg 6 +cartoon/house/pic_300.jpg 6 +cartoon/house/pic_303.jpg 6 +cartoon/house/pic_316.jpg 6 +cartoon/house/pic_317.jpg 6 +cartoon/house/pic_319.jpg 6 +cartoon/house/pic_039.jpg 6 +cartoon/house/pic_030.jpg 6 +cartoon/house/pic_034.jpg 6 +cartoon/house/pic_031.jpg 6 +cartoon/house/pic_038.jpg 6 +cartoon/house/pic_025.jpg 6 +cartoon/house/pic_051.jpg 6 +cartoon/house/pic_036.jpg 6 +cartoon/house/pic_041.jpg 6 +cartoon/house/pic_023.jpg 6 +cartoon/house/pic_046.jpg 6 +cartoon/house/pic_052.jpg 6 +cartoon/house/pic_040.jpg 6 +cartoon/house/pic_045.jpg 6 +cartoon/house/pic_044.jpg 6 +cartoon/house/pic_043.jpg 6 +cartoon/house/pic_042.jpg 6 +cartoon/house/pic_138.jpg 6 +cartoon/house/pic_140.jpg 6 +cartoon/house/pic_130.jpg 6 +cartoon/house/pic_143.jpg 6 +cartoon/house/pic_145.jpg 6 +cartoon/house/pic_146.jpg 6 +cartoon/house/pic_148.jpg 6 +cartoon/house/pic_147.jpg 6 +cartoon/house/pic_149.jpg 6 +cartoon/house/pic_152.jpg 6 +cartoon/house/pic_139.jpg 6 +cartoon/house/pic_153.jpg 6 +cartoon/house/pic_113.jpg 6 +cartoon/house/pic_116.jpg 6 +cartoon/house/pic_110.jpg 6 +cartoon/house/pic_122.jpg 6 +cartoon/house/pic_121.jpg 6 +cartoon/house/pic_120.jpg 6 +cartoon/house/pic_119.jpg 6 +cartoon/house/pic_118.jpg 6 +cartoon/house/pic_126.jpg 6 +cartoon/house/pic_123.jpg 6 +cartoon/house/pic_131.jpg 6 +cartoon/house/pic_132.jpg 6 +cartoon/house/pic_134.jpg 6 +cartoon/person/pic_074.jpg 7 +cartoon/person/pic_072.jpg 7 +cartoon/person/pic_077.jpg 7 +cartoon/person/pic_094.jpg 7 +cartoon/person/pic_123.jpg 7 +cartoon/person/pic_110.jpg 7 +cartoon/person/pic_109.jpg 7 +cartoon/person/pic_100.jpg 7 +cartoon/person/pic_095.jpg 7 +cartoon/person/pic_087.jpg 7 +cartoon/person/pic_089.jpg 7 +cartoon/person/pic_365.jpg 7 +cartoon/person/pic_373.jpg 7 +cartoon/person/pic_381.jpg 7 +cartoon/person/pic_379.jpg 7 +cartoon/person/pic_370.jpg 7 +cartoon/person/pic_374.jpg 7 +cartoon/person/pic_377.jpg 7 +cartoon/person/pic_380.jpg 7 +cartoon/person/pic_393.jpg 7 +cartoon/person/pic_392.jpg 7 +cartoon/person/pic_391.jpg 7 +cartoon/person/pic_389.jpg 7 +cartoon/person/pic_390.jpg 7 +cartoon/person/pic_387.jpg 7 +cartoon/person/pic_386.jpg 7 +cartoon/person/pic_385.jpg 7 +cartoon/person/pic_384.jpg 7 +cartoon/person/pic_383.jpg 7 +cartoon/person/pic_382.jpg 7 +cartoon/person/pic_001.jpg 7 +cartoon/person/pic_002.jpg 7 +cartoon/person/pic_003.jpg 7 +cartoon/person/pic_004.jpg 7 +cartoon/person/pic_085.jpg 7 +cartoon/person/pic_084.jpg 7 +cartoon/person/pic_083.jpg 7 +cartoon/person/pic_082.jpg 7 +cartoon/person/pic_081.jpg 7 +cartoon/person/pic_079.jpg 7 +cartoon/person/pic_078.jpg 7 +cartoon/person/pic_121.jpg 7 +cartoon/person/pic_117.jpg 7 +cartoon/person/pic_120.jpg 7 +cartoon/person/pic_105.jpg 7 +cartoon/person/pic_027.jpg 7 +cartoon/person/pic_025.jpg 7 +cartoon/person/pic_026.jpg 7 +cartoon/person/pic_022.jpg 7 +cartoon/person/pic_019.jpg 7 +cartoon/person/pic_030.jpg 7 +cartoon/person/pic_037.jpg 7 +cartoon/person/pic_036.jpg 7 +cartoon/person/pic_035.jpg 7 +cartoon/person/pic_032.jpg 7 +cartoon/person/pic_033.jpg 7 +cartoon/person/pic_031.jpg 7 +cartoon/person/pic_034.jpg 7 +cartoon/person/pic_038.jpg 7 +cartoon/person/pic_039.jpg 7 +cartoon/person/pic_040.jpg 7 +cartoon/person/pic_042.jpg 7 +cartoon/person/pic_043.jpg 7 +cartoon/person/pic_041.jpg 7 +cartoon/person/pic_049.jpg 7 +cartoon/person/pic_048.jpg 7 +cartoon/person/pic_415.jpg 7 +cartoon/person/pic_427.jpg 7 +cartoon/person/pic_429.jpg 7 +cartoon/person/pic_420.jpg 7 +cartoon/person/pic_423.jpg 7 +cartoon/person/pic_438.jpg 7 +cartoon/person/pic_434.jpg 7 +cartoon/person/pic_436.jpg 7 +cartoon/person/pic_432.jpg 7 +cartoon/person/pic_433.jpg 7 +cartoon/person/pic_431.jpg 7 +cartoon/person/pic_430.jpg 7 +cartoon/person/pic_439.jpg 7 +cartoon/person/pic_435.jpg 7 +cartoon/person/pic_445.jpg 7 +cartoon/person/pic_444.jpg 7 +cartoon/person/pic_441.jpg 7 +cartoon/person/pic_442.jpg 7 +cartoon/person/pic_443.jpg 7 +cartoon/person/pic_440.jpg 7 +cartoon/person/pic_005.jpg 7 +cartoon/person/pic_007.jpg 7 +cartoon/person/pic_008.jpg 7 +cartoon/person/pic_009.jpg 7 +cartoon/person/pic_010.jpg 7 +cartoon/person/pic_011.jpg 7 +cartoon/person/pic_012.jpg 7 +cartoon/person/pic_013.jpg 7 +cartoon/person/pic_014.jpg 7 +cartoon/person/pic_015.jpg 7 +cartoon/person/pic_021.jpg 7 +cartoon/person/pic_024.jpg 7 +cartoon/person/pic_023.jpg 7 +cartoon/person/pic_020.jpg 7 +cartoon/person/pic_018.jpg 7 +cartoon/person/pic_016.jpg 7 +cartoon/person/pic_017.jpg 7 +cartoon/person/pic_029.jpg 7 +cartoon/person/pic_028.jpg 7 +cartoon/person/pic_165.jpg 7 +cartoon/person/pic_164.jpg 7 +cartoon/person/pic_162.jpg 7 +cartoon/person/pic_158.jpg 7 +cartoon/person/pic_160.jpg 7 +cartoon/person/pic_172.jpg 7 +cartoon/person/pic_173.jpg 7 +cartoon/person/pic_170.jpg 7 +cartoon/person/pic_174.jpg 7 +cartoon/person/pic_161.jpg 7 +cartoon/person/pic_163.jpg 7 +cartoon/person/pic_175.jpg 7 +cartoon/person/pic_177.jpg 7 +cartoon/person/pic_180.jpg 7 +cartoon/person/pic_179.jpg 7 +cartoon/person/pic_181.jpg 7 +cartoon/person/pic_184.jpg 7 +cartoon/person/pic_185.jpg 7 +cartoon/person/pic_127.jpg 7 +cartoon/person/pic_113.jpg 7 +cartoon/person/pic_106.jpg 7 +cartoon/person/pic_129.jpg 7 +cartoon/person/pic_119.jpg 7 +cartoon/person/pic_125.jpg 7 +cartoon/person/pic_124.jpg 7 +cartoon/person/pic_147.jpg 7 +cartoon/person/pic_141.jpg 7 +cartoon/person/pic_140.jpg 7 +cartoon/person/pic_136.jpg 7 +cartoon/person/pic_137.jpg 7 +cartoon/person/pic_135.jpg 7 +cartoon/person/pic_133.jpg 7 +cartoon/person/pic_134.jpg 7 +cartoon/person/pic_132.jpg 7 +cartoon/person/pic_131.jpg 7 +cartoon/person/pic_146.jpg 7 +cartoon/person/pic_388.jpg 7 +cartoon/person/pic_400.jpg 7 +cartoon/person/pic_399.jpg 7 +cartoon/person/pic_402.jpg 7 +cartoon/person/pic_401.jpg 7 +cartoon/person/pic_394.jpg 7 +cartoon/person/pic_396.jpg 7 +cartoon/person/pic_395.jpg 7 +cartoon/person/pic_397.jpg 7 +cartoon/person/pic_398.jpg 7 +cartoon/person/pic_408.jpg 7 +cartoon/person/pic_403.jpg 7 +cartoon/person/pic_206.jpg 7 +cartoon/person/pic_209.jpg 7 +cartoon/person/pic_208.jpg 7 +cartoon/person/pic_207.jpg 7 +cartoon/person/pic_204.jpg 7 +cartoon/person/pic_216.jpg 7 +cartoon/person/pic_212.jpg 7 +cartoon/person/pic_210.jpg 7 +cartoon/person/pic_218.jpg 7 +cartoon/person/pic_221.jpg 7 +cartoon/person/pic_220.jpg 7 +cartoon/person/pic_222.jpg 7 +cartoon/person/pic_224.jpg 7 +cartoon/person/pic_225.jpg 7 +cartoon/person/pic_219.jpg 7 +cartoon/person/pic_226.jpg 7 +cartoon/person/pic_227.jpg 7 +cartoon/person/pic_451.jpg 7 +cartoon/person/pic_449.jpg 7 +cartoon/person/pic_450.jpg 7 +cartoon/person/pic_447.jpg 7 +cartoon/person/pic_448.jpg 7 +cartoon/person/pic_446.jpg 7 +cartoon/person/pic_453.jpg 7 +cartoon/person/pic_454.jpg 7 +cartoon/person/pic_452.jpg 7 +cartoon/person/pic_456.jpg 7 +cartoon/person/pic_458.jpg 7 +cartoon/person/pic_455.jpg 7 +cartoon/person/pic_457.jpg 7 +cartoon/person/pic_329.jpg 7 +cartoon/person/pic_330.jpg 7 +cartoon/person/pic_326.jpg 7 +cartoon/person/pic_327.jpg 7 +cartoon/person/pic_325.jpg 7 +cartoon/person/pic_328.jpg 7 +cartoon/person/pic_336.jpg 7 +cartoon/person/pic_338.jpg 7 +cartoon/person/pic_337.jpg 7 +cartoon/person/pic_340.jpg 7 +cartoon/person/pic_339.jpg 7 +cartoon/person/pic_342.jpg 7 +cartoon/person/pic_341.jpg 7 +cartoon/person/pic_343.jpg 7 +cartoon/person/pic_344.jpg 7 +cartoon/person/pic_347.jpg 7 +cartoon/person/pic_348.jpg 7 +cartoon/person/pic_350.jpg 7 +cartoon/person/pic_352.jpg 7 +cartoon/person/pic_047.jpg 7 +cartoon/person/pic_044.jpg 7 +cartoon/person/pic_045.jpg 7 +cartoon/person/pic_046.jpg 7 +cartoon/person/pic_052.jpg 7 +cartoon/person/pic_050.jpg 7 +cartoon/person/pic_053.jpg 7 +cartoon/person/pic_051.jpg 7 +cartoon/person/pic_067.jpg 7 +cartoon/person/pic_064.jpg 7 +cartoon/person/pic_063.jpg 7 +cartoon/person/pic_065.jpg 7 +cartoon/person/pic_060.jpg 7 +cartoon/person/pic_061.jpg 7 +cartoon/person/pic_059.jpg 7 +cartoon/person/pic_062.jpg 7 +cartoon/person/pic_055.jpg 7 +cartoon/person/pic_058.jpg 7 +cartoon/person/pic_054.jpg 7 +cartoon/person/pic_057.jpg 7 +cartoon/person/pic_093.jpg 7 +cartoon/person/pic_103.jpg 7 +cartoon/person/pic_104.jpg 7 +cartoon/person/pic_092.jpg 7 +cartoon/person/pic_090.jpg 7 +cartoon/person/pic_097.jpg 7 +cartoon/person/pic_080.jpg 7 +cartoon/person/pic_091.jpg 7 +cartoon/person/pic_122.jpg 7 +cartoon/person/pic_126.jpg 7 +cartoon/person/pic_112.jpg 7 +cartoon/person/pic_111.jpg 7 +cartoon/person/pic_101.jpg 7 +cartoon/person/pic_096.jpg 7 +cartoon/person/pic_130.jpg 7 +cartoon/person/pic_098.jpg 7 +cartoon/person/pic_102.jpg 7 +cartoon/person/pic_108.jpg 7 +cartoon/person/pic_114.jpg 7 +cartoon/person/pic_183.jpg 7 +cartoon/person/pic_186.jpg 7 +cartoon/person/pic_194.jpg 7 +cartoon/person/pic_188.jpg 7 +cartoon/person/pic_190.jpg 7 +cartoon/person/pic_193.jpg 7 +cartoon/person/pic_195.jpg 7 +cartoon/person/pic_199.jpg 7 +cartoon/person/pic_197.jpg 7 +cartoon/person/pic_200.jpg 7 +cartoon/person/pic_201.jpg 7 +cartoon/person/pic_203.jpg 7 +cartoon/person/pic_202.jpg 7 +cartoon/person/pic_217.jpg 7 +cartoon/person/pic_214.jpg 7 +cartoon/person/pic_215.jpg 7 +cartoon/person/pic_229.jpg 7 +cartoon/person/pic_228.jpg 7 +cartoon/person/pic_230.jpg 7 +cartoon/person/pic_236.jpg 7 +cartoon/person/pic_233.jpg 7 +cartoon/person/pic_232.jpg 7 +cartoon/person/pic_234.jpg 7 +cartoon/person/pic_231.jpg 7 +cartoon/person/pic_235.jpg 7 +cartoon/person/pic_240.jpg 7 +cartoon/person/pic_239.jpg 7 +cartoon/person/pic_237.jpg 7 +cartoon/person/pic_243.jpg 7 +cartoon/person/pic_242.jpg 7 +cartoon/person/pic_241.jpg 7 +cartoon/person/pic_244.jpg 7 +cartoon/person/pic_245.jpg 7 +cartoon/person/pic_246.jpg 7 +cartoon/person/pic_256.jpg 7 +cartoon/person/pic_254.jpg 7 +cartoon/person/pic_260.jpg 7 +cartoon/person/pic_270.jpg 7 +cartoon/person/pic_271.jpg 7 +cartoon/person/pic_273.jpg 7 +cartoon/person/pic_274.jpg 7 +cartoon/person/pic_275.jpg 7 +cartoon/person/pic_272.jpg 7 +cartoon/person/pic_276.jpg 7 +cartoon/person/pic_278.jpg 7 +cartoon/person/pic_297.jpg 7 +cartoon/person/pic_291.jpg 7 +cartoon/person/pic_293.jpg 7 +cartoon/person/pic_292.jpg 7 +cartoon/person/pic_289.jpg 7 +cartoon/person/pic_285.jpg 7 +cartoon/person/pic_283.jpg 7 +cartoon/person/pic_282.jpg 7 +cartoon/person/pic_286.jpg 7 +cartoon/person/pic_281.jpg 7 +cartoon/person/pic_280.jpg 7 +cartoon/person/pic_279.jpg 7 +cartoon/person/pic_277.jpg 7 +cartoon/person/pic_301.jpg 7 +cartoon/person/pic_298.jpg 7 +cartoon/person/pic_302.jpg 7 +cartoon/person/pic_294.jpg 7 +cartoon/person/pic_299.jpg 7 +cartoon/person/pic_284.jpg 7 +cartoon/person/pic_287.jpg 7 +cartoon/person/pic_305.jpg 7 +cartoon/person/pic_296.jpg 7 +cartoon/person/pic_300.jpg 7 +cartoon/person/pic_295.jpg 7 +cartoon/person/pic_303.jpg 7 +cartoon/person/pic_315.jpg 7 +cartoon/person/pic_314.jpg 7 +cartoon/person/pic_310.jpg 7 +cartoon/person/pic_405.jpg 7 +cartoon/person/pic_404.jpg 7 +cartoon/person/pic_406.jpg 7 +cartoon/person/pic_413.jpg 7 +cartoon/person/pic_411.jpg 7 +cartoon/person/pic_410.jpg 7 +cartoon/person/pic_409.jpg 7 +cartoon/person/pic_412.jpg 7 +cartoon/person/pic_426.jpg 7 +cartoon/person/pic_428.jpg 7 +cartoon/person/pic_425.jpg 7 +cartoon/person/pic_424.jpg 7 +cartoon/person/pic_421.jpg 7 +cartoon/person/pic_417.jpg 7 +cartoon/person/pic_419.jpg 7 +cartoon/person/pic_418.jpg 7 +cartoon/person/pic_416.jpg 7 +cartoon/person/pic_351.jpg 7 +cartoon/person/pic_349.jpg 7 +cartoon/person/pic_363.jpg 7 +cartoon/person/pic_358.jpg 7 +cartoon/person/pic_357.jpg 7 +cartoon/person/pic_354.jpg 7 +cartoon/person/pic_353.jpg 7 +cartoon/person/pic_360.jpg 7 +cartoon/person/pic_362.jpg 7 +cartoon/person/pic_359.jpg 7 +cartoon/person/pic_366.jpg 7 +cartoon/person/pic_375.jpg 7 +cartoon/person/pic_376.jpg 7 +cartoon/person/pic_372.jpg 7 +cartoon/person/pic_371.jpg 7 +cartoon/person/pic_369.jpg 7 +cartoon/person/pic_368.jpg 7 +cartoon/person/pic_364.jpg 7 +cartoon/person/pic_251.jpg 7 +cartoon/person/pic_250.jpg 7 +cartoon/person/pic_252.jpg 7 +cartoon/person/pic_248.jpg 7 +cartoon/person/pic_247.jpg 7 +cartoon/person/pic_249.jpg 7 +cartoon/person/pic_257.jpg 7 +cartoon/person/pic_253.jpg 7 +cartoon/person/pic_259.jpg 7 +cartoon/person/pic_268.jpg 7 +cartoon/person/pic_264.jpg 7 +cartoon/person/pic_265.jpg 7 +cartoon/person/pic_262.jpg 7 +cartoon/person/pic_261.jpg 7 +cartoon/person/pic_255.jpg 7 diff --git a/domainlab/zdata/pacs_split/photo_10.txt b/domainlab/zdata/pacs_split/photo_10.txt new file mode 100644 index 000000000..59ba86d76 --- /dev/null +++ b/domainlab/zdata/pacs_split/photo_10.txt @@ -0,0 +1,10 @@ +photo/house/pic_218.jpg 6 +photo/horse/105_0223.jpg 5 +photo/house/pic_046.jpg 6 +photo/house/pic_110.jpg 6 +photo/elephant/n02503517_6232.jpg 2 +photo/dog/n02103406_1011.jpg 1 +photo/house/pic_146.jpg 6 +photo/guitar/n02676566_7830.jpg 4 +photo/person/253_0221.jpg 7 +photo/person/253_0297.jpg 7 diff --git a/domainlab/zdata/pacs_split/photo_100.txt b/domainlab/zdata/pacs_split/photo_100.txt new file mode 100644 index 000000000..9a0951918 --- /dev/null +++ b/domainlab/zdata/pacs_split/photo_100.txt @@ -0,0 +1,100 @@ +photo/horse/105_0120.jpg 5 +photo/giraffe/084_0074.jpg 3 +photo/person/253_0089.jpg 7 +photo/dog/056_0041.jpg 1 +photo/horse/n02374451_12254.jpg 5 +photo/horse/n02374451_18909.jpg 5 +photo/person/253_0366.jpg 7 +photo/guitar/n03467517_11020.jpg 4 +photo/dog/n02103406_3056.jpg 1 +photo/elephant/064_0065.jpg 2 +photo/guitar/063_0067.jpg 4 +photo/giraffe/n02439033_221.jpg 3 +photo/person/253_0166.jpg 7 +photo/guitar/063_0071.jpg 4 +photo/elephant/n02503517_1292.jpg 2 +photo/house/pic_043.jpg 6 +photo/elephant/n02503517_5527.jpg 2 +photo/person/253_0098.jpg 7 +photo/horse/105_0185.jpg 5 +photo/guitar/n02676566_12344.jpg 4 +photo/person/253_0108.jpg 7 +photo/elephant/n02503517_6396.jpg 2 +photo/person/253_0349.jpg 7 +photo/guitar/063_0050.jpg 4 +photo/house/pic_111.jpg 6 +photo/dog/056_0085.jpg 1 +photo/horse/105_0066.jpg 5 +photo/house/pic_044.jpg 6 +photo/house/pic_113.jpg 6 +photo/person/253_0258.jpg 7 +photo/elephant/n02503517_10275.jpg 2 +photo/horse/n02374451_4553.jpg 5 +photo/person/253_0186.jpg 7 +photo/elephant/064_0055.jpg 2 +photo/person/253_0266.jpg 7 +photo/person/253_0205.jpg 7 +photo/person/253_0246.jpg 7 +photo/house/pic_181.jpg 6 +photo/elephant/064_0080.jpg 2 +photo/person/253_0236.jpg 7 +photo/elephant/n02503517_3879.jpg 2 +photo/person/253_0331.jpg 7 +photo/house/pic_071.jpg 6 +photo/house/pic_061.jpg 6 +photo/dog/056_0050.jpg 1 +photo/house/pic_067.jpg 6 +photo/person/253_0057.jpg 7 +photo/elephant/064_0022.jpg 2 +photo/person/253_0175.jpg 7 +photo/person/253_0143.jpg 7 +photo/house/pic_193.jpg 6 +photo/elephant/n02503517_86.jpg 2 +photo/elephant/064_0049.jpg 2 +photo/house/pic_099.jpg 6 +photo/house/pic_229.jpg 6 +photo/person/253_0323.jpg 7 +photo/giraffe/084_0075.jpg 3 +photo/guitar/063_0092.jpg 4 +photo/dog/056_0064.jpg 1 +photo/giraffe/n02439033_11487.jpg 3 +photo/house/pic_006.jpg 6 +photo/guitar/n03467517_24525.jpg 4 +photo/house/pic_265.jpg 6 +photo/person/253_0097.jpg 7 +photo/guitar/n03272010_6809.jpg 4 +photo/elephant/n02503517_5909.jpg 2 +photo/guitar/n02676566_659.jpg 4 +photo/elephant/064_0125.jpg 2 +photo/house/pic_263.jpg 6 +photo/house/pic_073.jpg 6 +photo/person/253_0383.jpg 7 +photo/giraffe/084_0064.jpg 3 +photo/person/253_0421.jpg 7 +photo/guitar/063_0052.jpg 4 +photo/house/pic_030.jpg 6 +photo/person/253_0156.jpg 7 +photo/person/253_0053.jpg 7 +photo/giraffe/n02439033_10453.jpg 3 +photo/house/pic_096.jpg 6 +photo/giraffe/n02439033_13384.jpg 3 +photo/house/pic_233.jpg 6 +photo/horse/105_0059.jpg 5 +photo/person/253_0219.jpg 7 +photo/person/253_0283.jpg 7 +photo/horse/n02374451_13159.jpg 5 +photo/guitar/n03272010_6799.jpg 4 +photo/elephant/n02503517_7393.jpg 2 +photo/horse/n02374451_777.jpg 5 +photo/giraffe/084_0072.jpg 3 +photo/person/253_0427.jpg 7 +photo/person/253_0405.jpg 7 +photo/horse/105_0056.jpg 5 +photo/guitar/063_0085.jpg 4 +photo/horse/n02374451_2248.jpg 5 +photo/person/253_0377.jpg 7 +photo/horse/n02374451_1443.jpg 5 +photo/guitar/063_0121.jpg 4 +photo/elephant/064_0038.jpg 2 +photo/elephant/064_0078.jpg 2 +photo/elephant/064_0079.jpg 2 diff --git a/domainlab/zdata/pacs_split/photo_crossval_kfold.txt b/domainlab/zdata/pacs_split/photo_crossval_kfold.txt new file mode 100644 index 000000000..e001ac79e --- /dev/null +++ b/domainlab/zdata/pacs_split/photo_crossval_kfold.txt @@ -0,0 +1,171 @@ +photo/dog/056_0001.jpg 1 +photo/dog/056_0002.jpg 1 +photo/dog/056_0003.jpg 1 +photo/dog/056_0004.jpg 1 +photo/dog/056_0005.jpg 1 +photo/dog/056_0006.jpg 1 +photo/dog/056_0007.jpg 1 +photo/dog/056_0009.jpg 1 +photo/dog/056_0010.jpg 1 +photo/dog/056_0011.jpg 1 +photo/dog/056_0012.jpg 1 +photo/dog/056_0013.jpg 1 +photo/dog/056_0014.jpg 1 +photo/dog/056_0015.jpg 1 +photo/dog/056_0016.jpg 1 +photo/dog/056_0017.jpg 1 +photo/dog/056_0018.jpg 1 +photo/dog/056_0020.jpg 1 +photo/dog/056_0021.jpg 1 +photo/elephant/064_0001.jpg 2 +photo/elephant/064_0002.jpg 2 +photo/elephant/064_0003.jpg 2 +photo/elephant/064_0004.jpg 2 +photo/elephant/064_0005.jpg 2 +photo/elephant/064_0006.jpg 2 +photo/elephant/064_0007.jpg 2 +photo/elephant/064_0008.jpg 2 +photo/elephant/064_0009.jpg 2 +photo/elephant/064_0010.jpg 2 +photo/elephant/064_0011.jpg 2 +photo/elephant/064_0012.jpg 2 +photo/elephant/064_0013.jpg 2 +photo/elephant/064_0014.jpg 2 +photo/elephant/064_0015.jpg 2 +photo/elephant/064_0016.jpg 2 +photo/elephant/064_0017.jpg 2 +photo/elephant/064_0018.jpg 2 +photo/elephant/064_0019.jpg 2 +photo/elephant/064_0020.jpg 2 +photo/elephant/064_0021.jpg 2 +photo/giraffe/084_0001.jpg 3 +photo/giraffe/084_0002.jpg 3 +photo/giraffe/084_0003.jpg 3 +photo/giraffe/084_0004.jpg 3 +photo/giraffe/084_0005.jpg 3 +photo/giraffe/084_0006.jpg 3 +photo/giraffe/084_0007.jpg 3 +photo/giraffe/084_0008.jpg 3 +photo/giraffe/084_0009.jpg 3 +photo/giraffe/084_0010.jpg 3 +photo/giraffe/084_0011.jpg 3 +photo/giraffe/084_0012.jpg 3 +photo/giraffe/084_0013.jpg 3 +photo/giraffe/084_0014.jpg 3 +photo/giraffe/084_0015.jpg 3 +photo/giraffe/084_0016.jpg 3 +photo/giraffe/084_0017.jpg 3 +photo/giraffe/084_0018.jpg 3 +photo/giraffe/084_0019.jpg 3 +photo/guitar/063_0001.jpg 4 +photo/guitar/063_0002.jpg 4 +photo/guitar/063_0003.jpg 4 +photo/guitar/063_0004.jpg 4 +photo/guitar/063_0005.jpg 4 +photo/guitar/063_0006.jpg 4 +photo/guitar/063_0007.jpg 4 +photo/guitar/063_0008.jpg 4 +photo/guitar/063_0009.jpg 4 +photo/guitar/063_0010.jpg 4 +photo/guitar/063_0012.jpg 4 +photo/guitar/063_0013.jpg 4 +photo/guitar/063_0016.jpg 4 +photo/guitar/063_0018.jpg 4 +photo/guitar/063_0019.jpg 4 +photo/guitar/063_0020.jpg 4 +photo/guitar/063_0021.jpg 4 +photo/guitar/063_0022.jpg 4 +photo/guitar/063_0023.jpg 4 +photo/horse/105_0002.jpg 5 +photo/horse/105_0003.jpg 5 +photo/horse/105_0007.jpg 5 +photo/horse/105_0008.jpg 5 +photo/horse/105_0009.jpg 5 +photo/horse/105_0010.jpg 5 +photo/horse/105_0012.jpg 5 +photo/horse/105_0013.jpg 5 +photo/horse/105_0022.jpg 5 +photo/horse/105_0025.jpg 5 +photo/horse/105_0028.jpg 5 +photo/horse/105_0029.jpg 5 +photo/horse/105_0030.jpg 5 +photo/horse/105_0033.jpg 5 +photo/horse/105_0037.jpg 5 +photo/horse/105_0038.jpg 5 +photo/horse/105_0041.jpg 5 +photo/horse/105_0042.jpg 5 +photo/horse/105_0047.jpg 5 +photo/horse/105_0048.jpg 5 +photo/house/pic_010.jpg 6 +photo/house/pic_011.jpg 6 +photo/house/pic_012.jpg 6 +photo/house/pic_013.jpg 6 +photo/house/pic_014.jpg 6 +photo/house/pic_015.jpg 6 +photo/house/pic_016.jpg 6 +photo/house/pic_017.jpg 6 +photo/house/pic_018.jpg 6 +photo/house/pic_021.jpg 6 +photo/house/pic_019.jpg 6 +photo/house/pic_022.jpg 6 +photo/house/pic_020.jpg 6 +photo/house/pic_023.jpg 6 +photo/house/pic_024.jpg 6 +photo/house/pic_026.jpg 6 +photo/house/pic_025.jpg 6 +photo/house/pic_027.jpg 6 +photo/house/pic_028.jpg 6 +photo/house/pic_029.jpg 6 +photo/house/pic_031.jpg 6 +photo/house/pic_239.jpg 6 +photo/house/pic_240.jpg 6 +photo/house/pic_241.jpg 6 +photo/house/pic_242.jpg 6 +photo/house/pic_248.jpg 6 +photo/house/pic_246.jpg 6 +photo/house/pic_247.jpg 6 +photo/house/pic_244.jpg 6 +photo/person/253_0001.jpg 7 +photo/person/253_0002.jpg 7 +photo/person/253_0003.jpg 7 +photo/person/253_0004.jpg 7 +photo/person/253_0005.jpg 7 +photo/person/253_0006.jpg 7 +photo/person/253_0007.jpg 7 +photo/person/253_0008.jpg 7 +photo/person/253_0009.jpg 7 +photo/person/253_0010.jpg 7 +photo/person/253_0011.jpg 7 +photo/person/253_0012.jpg 7 +photo/person/253_0013.jpg 7 +photo/person/253_0014.jpg 7 +photo/person/253_0015.jpg 7 +photo/person/253_0016.jpg 7 +photo/person/253_0017.jpg 7 +photo/person/253_0018.jpg 7 +photo/person/253_0019.jpg 7 +photo/person/253_0020.jpg 7 +photo/person/253_0021.jpg 7 +photo/person/253_0022.jpg 7 +photo/person/253_0023.jpg 7 +photo/person/253_0024.jpg 7 +photo/person/253_0025.jpg 7 +photo/person/253_0026.jpg 7 +photo/person/253_0027.jpg 7 +photo/person/253_0028.jpg 7 +photo/person/253_0029.jpg 7 +photo/person/253_0030.jpg 7 +photo/person/253_0031.jpg 7 +photo/person/253_0032.jpg 7 +photo/person/253_0033.jpg 7 +photo/person/253_0034.jpg 7 +photo/person/253_0035.jpg 7 +photo/person/253_0036.jpg 7 +photo/person/253_0037.jpg 7 +photo/person/253_0038.jpg 7 +photo/person/253_0039.jpg 7 +photo/person/253_0040.jpg 7 +photo/person/253_0041.jpg 7 +photo/person/253_0042.jpg 7 +photo/person/253_0043.jpg 7 +photo/person/253_0044.jpg 7 diff --git a/domainlab/zdata/pacs_split/photo_test_kfold.txt b/domainlab/zdata/pacs_split/photo_test_kfold.txt new file mode 100644 index 000000000..643ed4aa8 --- /dev/null +++ b/domainlab/zdata/pacs_split/photo_test_kfold.txt @@ -0,0 +1,1670 @@ +photo/dog/056_0001.jpg 1 +photo/dog/056_0002.jpg 1 +photo/dog/056_0003.jpg 1 +photo/dog/056_0004.jpg 1 +photo/dog/056_0005.jpg 1 +photo/dog/056_0006.jpg 1 +photo/dog/056_0007.jpg 1 +photo/dog/056_0009.jpg 1 +photo/dog/056_0010.jpg 1 +photo/dog/056_0011.jpg 1 +photo/dog/056_0012.jpg 1 +photo/dog/056_0013.jpg 1 +photo/dog/056_0014.jpg 1 +photo/dog/056_0015.jpg 1 +photo/dog/056_0016.jpg 1 +photo/dog/056_0017.jpg 1 +photo/dog/056_0018.jpg 1 +photo/dog/056_0020.jpg 1 +photo/dog/056_0021.jpg 1 +photo/dog/056_0022.jpg 1 +photo/dog/056_0023.jpg 1 +photo/dog/056_0024.jpg 1 +photo/dog/056_0026.jpg 1 +photo/dog/056_0027.jpg 1 +photo/dog/056_0028.jpg 1 +photo/dog/056_0029.jpg 1 +photo/dog/056_0030.jpg 1 +photo/dog/056_0031.jpg 1 +photo/dog/056_0032.jpg 1 +photo/dog/056_0033.jpg 1 +photo/dog/056_0034.jpg 1 +photo/dog/056_0035.jpg 1 +photo/dog/056_0036.jpg 1 +photo/dog/056_0037.jpg 1 +photo/dog/056_0038.jpg 1 +photo/dog/056_0039.jpg 1 +photo/dog/056_0040.jpg 1 +photo/dog/056_0041.jpg 1 +photo/dog/056_0042.jpg 1 +photo/dog/056_0043.jpg 1 +photo/dog/056_0045.jpg 1 +photo/dog/056_0046.jpg 1 +photo/dog/056_0047.jpg 1 +photo/dog/056_0048.jpg 1 +photo/dog/056_0049.jpg 1 +photo/dog/056_0050.jpg 1 +photo/dog/056_0051.jpg 1 +photo/dog/056_0052.jpg 1 +photo/dog/056_0053.jpg 1 +photo/dog/056_0054.jpg 1 +photo/dog/056_0055.jpg 1 +photo/dog/056_0056.jpg 1 +photo/dog/056_0057.jpg 1 +photo/dog/056_0058.jpg 1 +photo/dog/056_0059.jpg 1 +photo/dog/056_0060.jpg 1 +photo/dog/056_0062.jpg 1 +photo/dog/056_0063.jpg 1 +photo/dog/056_0064.jpg 1 +photo/dog/056_0065.jpg 1 +photo/dog/056_0066.jpg 1 +photo/dog/056_0067.jpg 1 +photo/dog/056_0068.jpg 1 +photo/dog/056_0069.jpg 1 +photo/dog/056_0070.jpg 1 +photo/dog/056_0071.jpg 1 +photo/dog/056_0072.jpg 1 +photo/dog/056_0073.jpg 1 +photo/dog/056_0074.jpg 1 +photo/dog/056_0075.jpg 1 +photo/dog/056_0076.jpg 1 +photo/dog/056_0077.jpg 1 +photo/dog/056_0078.jpg 1 +photo/dog/056_0079.jpg 1 +photo/dog/056_0080.jpg 1 +photo/dog/056_0081.jpg 1 +photo/dog/056_0082.jpg 1 +photo/dog/056_0083.jpg 1 +photo/dog/056_0084.jpg 1 +photo/dog/056_0085.jpg 1 +photo/dog/056_0086.jpg 1 +photo/dog/056_0087.jpg 1 +photo/dog/056_0088.jpg 1 +photo/dog/056_0089.jpg 1 +photo/dog/056_0090.jpg 1 +photo/dog/056_0091.jpg 1 +photo/dog/056_0092.jpg 1 +photo/dog/056_0093.jpg 1 +photo/dog/056_0095.jpg 1 +photo/dog/056_0097.jpg 1 +photo/dog/056_0098.jpg 1 +photo/dog/056_0099.jpg 1 +photo/dog/056_0101.jpg 1 +photo/dog/056_0102.jpg 1 +photo/dog/n02103406_343.jpg 1 +photo/dog/n02103406_346.jpg 1 +photo/dog/n02103406_371.jpg 1 +photo/dog/n02103406_865.jpg 1 +photo/dog/n02103406_936.jpg 1 +photo/dog/n02103406_995.jpg 1 +photo/dog/n02103406_1011.jpg 1 +photo/dog/n02103406_1138.jpg 1 +photo/dog/n02103406_1170.jpg 1 +photo/dog/n02103406_1247.jpg 1 +photo/dog/n02103406_1599.jpg 1 +photo/dog/n02103406_1754.jpg 1 +photo/dog/n02103406_2209.jpg 1 +photo/dog/n02103406_2706.jpg 1 +photo/dog/n02103406_2954.jpg 1 +photo/dog/n02103406_3056.jpg 1 +photo/dog/n02103406_3108.jpg 1 +photo/dog/n02103406_3132.jpg 1 +photo/dog/n02103406_3255.jpg 1 +photo/dog/n02103406_3299.jpg 1 +photo/dog/n02103406_3326.jpg 1 +photo/dog/n02103406_3401.jpg 1 +photo/dog/n02103406_3538.jpg 1 +photo/dog/n02103406_3743.jpg 1 +photo/dog/n02103406_3750.jpg 1 +photo/dog/n02103406_3964.jpg 1 +photo/dog/n02103406_4068.jpg 1 +photo/dog/n02103406_4849.jpg 1 +photo/dog/n02103406_4916.jpg 1 +photo/dog/n02103406_5035.jpg 1 +photo/dog/n02103406_5216.jpg 1 +photo/dog/n02103406_5224.jpg 1 +photo/dog/n02103406_5456.jpg 1 +photo/dog/n02103406_5505.jpg 1 +photo/dog/n02103406_5563.jpg 1 +photo/dog/n02103406_5601.jpg 1 +photo/dog/n02103406_6274.jpg 1 +photo/dog/n02103406_6461.jpg 1 +photo/dog/n02103406_6530.jpg 1 +photo/dog/n02103406_6857.jpg 1 +photo/dog/n02103406_7201.jpg 1 +photo/dog/n02103406_7368.jpg 1 +photo/dog/n02103406_7521.jpg 1 +photo/dog/n02103406_7708.jpg 1 +photo/dog/n02103406_8004.jpg 1 +photo/dog/n02103406_8280.jpg 1 +photo/dog/n02103406_8362.jpg 1 +photo/dog/n02103406_8421.jpg 1 +photo/dog/n02103406_13049.jpg 1 +photo/dog/n02106662_466.jpg 1 +photo/dog/n02106662_928.jpg 1 +photo/dog/n02106662_1874.jpg 1 +photo/dog/n02106662_1922.jpg 1 +photo/dog/n02106662_2101.jpg 1 +photo/dog/n02106662_2157.jpg 1 +photo/dog/n02106662_2377.jpg 1 +photo/dog/n02106662_2740.jpg 1 +photo/dog/n02106662_5001.jpg 1 +photo/dog/n02106662_7885.jpg 1 +photo/dog/n02106662_7960.jpg 1 +photo/dog/n02106662_8511.jpg 1 +photo/dog/n02106662_8870.jpg 1 +photo/dog/n02106662_10406.jpg 1 +photo/dog/n02106662_11133.jpg 1 +photo/dog/n02106662_13178.jpg 1 +photo/dog/n02106662_13912.jpg 1 +photo/dog/n02106662_15858.jpg 1 +photo/dog/n02106662_18402.jpg 1 +photo/dog/n02106662_18405.jpg 1 +photo/dog/n02106662_18922.jpg 1 +photo/dog/n02106662_18953.jpg 1 +photo/dog/n02106662_24019.jpg 1 +photo/dog/n02106662_24577.jpg 1 +photo/dog/n02106662_24786.jpg 1 +photo/dog/n02106662_25917.jpg 1 +photo/dog/n02106662_26549.jpg 1 +photo/dog/n02106662_27393.jpg 1 +photo/dog/n02109525_704.jpg 1 +photo/dog/n02109525_1893.jpg 1 +photo/dog/n02109525_3202.jpg 1 +photo/dog/n02109525_3782.jpg 1 +photo/dog/n02109525_5013.jpg 1 +photo/dog/n02109525_5583.jpg 1 +photo/dog/n02109525_5966.jpg 1 +photo/dog/n02109525_6693.jpg 1 +photo/dog/n02109525_7874.jpg 1 +photo/dog/n02109525_8211.jpg 1 +photo/dog/n02109525_8457.jpg 1 +photo/dog/n02109525_9037.jpg 1 +photo/dog/n02109525_10297.jpg 1 +photo/dog/n02109525_11444.jpg 1 +photo/dog/n02109525_12875.jpg 1 +photo/dog/n02109525_13700.jpg 1 +photo/dog/n02109525_16346.jpg 1 +photo/dog/n02109525_18347.jpg 1 +photo/elephant/064_0001.jpg 2 +photo/elephant/064_0002.jpg 2 +photo/elephant/064_0003.jpg 2 +photo/elephant/064_0004.jpg 2 +photo/elephant/064_0005.jpg 2 +photo/elephant/064_0006.jpg 2 +photo/elephant/064_0007.jpg 2 +photo/elephant/064_0008.jpg 2 +photo/elephant/064_0009.jpg 2 +photo/elephant/064_0010.jpg 2 +photo/elephant/064_0011.jpg 2 +photo/elephant/064_0012.jpg 2 +photo/elephant/064_0013.jpg 2 +photo/elephant/064_0014.jpg 2 +photo/elephant/064_0015.jpg 2 +photo/elephant/064_0016.jpg 2 +photo/elephant/064_0017.jpg 2 +photo/elephant/064_0018.jpg 2 +photo/elephant/064_0019.jpg 2 +photo/elephant/064_0020.jpg 2 +photo/elephant/064_0021.jpg 2 +photo/elephant/064_0022.jpg 2 +photo/elephant/064_0023.jpg 2 +photo/elephant/064_0024.jpg 2 +photo/elephant/064_0025.jpg 2 +photo/elephant/064_0030.jpg 2 +photo/elephant/064_0031.jpg 2 +photo/elephant/064_0032.jpg 2 +photo/elephant/064_0033.jpg 2 +photo/elephant/064_0034.jpg 2 +photo/elephant/064_0035.jpg 2 +photo/elephant/064_0036.jpg 2 +photo/elephant/064_0037.jpg 2 +photo/elephant/064_0038.jpg 2 +photo/elephant/064_0039.jpg 2 +photo/elephant/064_0040.jpg 2 +photo/elephant/064_0041.jpg 2 +photo/elephant/064_0042.jpg 2 +photo/elephant/064_0043.jpg 2 +photo/elephant/064_0044.jpg 2 +photo/elephant/064_0045.jpg 2 +photo/elephant/064_0047.jpg 2 +photo/elephant/064_0048.jpg 2 +photo/elephant/064_0049.jpg 2 +photo/elephant/064_0051.jpg 2 +photo/elephant/064_0052.jpg 2 +photo/elephant/064_0053.jpg 2 +photo/elephant/064_0054.jpg 2 +photo/elephant/064_0055.jpg 2 +photo/elephant/064_0056.jpg 2 +photo/elephant/064_0057.jpg 2 +photo/elephant/064_0058.jpg 2 +photo/elephant/064_0059.jpg 2 +photo/elephant/064_0060.jpg 2 +photo/elephant/064_0061.jpg 2 +photo/elephant/064_0062.jpg 2 +photo/elephant/064_0063.jpg 2 +photo/elephant/064_0064.jpg 2 +photo/elephant/064_0065.jpg 2 +photo/elephant/064_0066.jpg 2 +photo/elephant/064_0067.jpg 2 +photo/elephant/064_0068.jpg 2 +photo/elephant/064_0070.jpg 2 +photo/elephant/064_0071.jpg 2 +photo/elephant/064_0072.jpg 2 +photo/elephant/064_0073.jpg 2 +photo/elephant/064_0074.jpg 2 +photo/elephant/064_0075.jpg 2 +photo/elephant/064_0076.jpg 2 +photo/elephant/064_0077.jpg 2 +photo/elephant/064_0078.jpg 2 +photo/elephant/064_0079.jpg 2 +photo/elephant/064_0080.jpg 2 +photo/elephant/064_0081.jpg 2 +photo/elephant/064_0084.jpg 2 +photo/elephant/064_0085.jpg 2 +photo/elephant/064_0086.jpg 2 +photo/elephant/064_0087.jpg 2 +photo/elephant/064_0088.jpg 2 +photo/elephant/064_0089.jpg 2 +photo/elephant/064_0090.jpg 2 +photo/elephant/064_0092.jpg 2 +photo/elephant/064_0093.jpg 2 +photo/elephant/064_0094.jpg 2 +photo/elephant/064_0095.jpg 2 +photo/elephant/064_0096.jpg 2 +photo/elephant/064_0097.jpg 2 +photo/elephant/064_0098.jpg 2 +photo/elephant/064_0099.jpg 2 +photo/elephant/064_0100.jpg 2 +photo/elephant/064_0101.jpg 2 +photo/elephant/064_0102.jpg 2 +photo/elephant/064_0105.jpg 2 +photo/elephant/064_0106.jpg 2 +photo/elephant/064_0107.jpg 2 +photo/elephant/064_0108.jpg 2 +photo/elephant/064_0109.jpg 2 +photo/elephant/064_0110.jpg 2 +photo/elephant/064_0111.jpg 2 +photo/elephant/064_0112.jpg 2 +photo/elephant/064_0113.jpg 2 +photo/elephant/064_0114.jpg 2 +photo/elephant/064_0115.jpg 2 +photo/elephant/064_0116.jpg 2 +photo/elephant/064_0117.jpg 2 +photo/elephant/064_0118.jpg 2 +photo/elephant/064_0119.jpg 2 +photo/elephant/064_0120.jpg 2 +photo/elephant/064_0121.jpg 2 +photo/elephant/064_0122.jpg 2 +photo/elephant/064_0123.jpg 2 +photo/elephant/064_0124.jpg 2 +photo/elephant/064_0125.jpg 2 +photo/elephant/064_0126.jpg 2 +photo/elephant/064_0127.jpg 2 +photo/elephant/064_0129.jpg 2 +photo/elephant/064_0130.jpg 2 +photo/elephant/064_0131.jpg 2 +photo/elephant/n02503517_79.jpg 2 +photo/elephant/n02503517_86.jpg 2 +photo/elephant/n02503517_184.jpg 2 +photo/elephant/n02503517_194.jpg 2 +photo/elephant/n02503517_564.jpg 2 +photo/elephant/n02503517_753.jpg 2 +photo/elephant/n02503517_759.jpg 2 +photo/elephant/n02503517_792.jpg 2 +photo/elephant/n02503517_1292.jpg 2 +photo/elephant/n02503517_1359.jpg 2 +photo/elephant/n02503517_1383.jpg 2 +photo/elephant/n02503517_1415.jpg 2 +photo/elephant/n02503517_1453.jpg 2 +photo/elephant/n02503517_1583.jpg 2 +photo/elephant/n02503517_1829.jpg 2 +photo/elephant/n02503517_2061.jpg 2 +photo/elephant/n02503517_2444.jpg 2 +photo/elephant/n02503517_2547.jpg 2 +photo/elephant/n02503517_2802.jpg 2 +photo/elephant/n02503517_2804.jpg 2 +photo/elephant/n02503517_2925.jpg 2 +photo/elephant/n02503517_2993.jpg 2 +photo/elephant/n02503517_3037.jpg 2 +photo/elephant/n02503517_3072.jpg 2 +photo/elephant/n02503517_3108.jpg 2 +photo/elephant/n02503517_3799.jpg 2 +photo/elephant/n02503517_3803.jpg 2 +photo/elephant/n02503517_3808.jpg 2 +photo/elephant/n02503517_3879.jpg 2 +photo/elephant/n02503517_4221.jpg 2 +photo/elephant/n02503517_4247.jpg 2 +photo/elephant/n02503517_4253.jpg 2 +photo/elephant/n02503517_4413.jpg 2 +photo/elephant/n02503517_4605.jpg 2 +photo/elephant/n02503517_5117.jpg 2 +photo/elephant/n02503517_5287.jpg 2 +photo/elephant/n02503517_5418.jpg 2 +photo/elephant/n02503517_5420.jpg 2 +photo/elephant/n02503517_5527.jpg 2 +photo/elephant/n02503517_5892.jpg 2 +photo/elephant/n02503517_5909.jpg 2 +photo/elephant/n02503517_6032.jpg 2 +photo/elephant/n02503517_6232.jpg 2 +photo/elephant/n02503517_6396.jpg 2 +photo/elephant/n02503517_6479.jpg 2 +photo/elephant/n02503517_6611.jpg 2 +photo/elephant/n02503517_6624.jpg 2 +photo/elephant/n02503517_6661.jpg 2 +photo/elephant/n02503517_6784.jpg 2 +photo/elephant/n02503517_6880.jpg 2 +photo/elephant/n02503517_7020.jpg 2 +photo/elephant/n02503517_7031.jpg 2 +photo/elephant/n02503517_7083.jpg 2 +photo/elephant/n02503517_7173.jpg 2 +photo/elephant/n02503517_7211.jpg 2 +photo/elephant/n02503517_7393.jpg 2 +photo/elephant/n02503517_8137.jpg 2 +photo/elephant/n02503517_8205.jpg 2 +photo/elephant/n02503517_8222.jpg 2 +photo/elephant/n02503517_8265.jpg 2 +photo/elephant/n02503517_8292.jpg 2 +photo/elephant/n02503517_8518.jpg 2 +photo/elephant/n02503517_8571.jpg 2 +photo/elephant/n02503517_8757.jpg 2 +photo/elephant/n02503517_8901.jpg 2 +photo/elephant/n02503517_8904.jpg 2 +photo/elephant/n02503517_8938.jpg 2 +photo/elephant/n02503517_9043.jpg 2 +photo/elephant/n02503517_9154.jpg 2 +photo/elephant/n02503517_9241.jpg 2 +photo/elephant/n02503517_9270.jpg 2 +photo/elephant/n02503517_9827.jpg 2 +photo/elephant/n02503517_10036.jpg 2 +photo/elephant/n02503517_10075.jpg 2 +photo/elephant/n02503517_10193.jpg 2 +photo/elephant/n02503517_10275.jpg 2 +photo/elephant/n02503517_10300.jpg 2 +photo/elephant/n02503517_10439.jpg 2 +photo/elephant/n02503517_10440.jpg 2 +photo/elephant/n02503517_10528.jpg 2 +photo/elephant/n02503517_10558.jpg 2 +photo/elephant/n02503517_10778.jpg 2 +photo/elephant/n02503517_11873.jpg 2 +photo/elephant/n02503517_12688.jpg 2 +photo/giraffe/084_0001.jpg 3 +photo/giraffe/084_0002.jpg 3 +photo/giraffe/084_0003.jpg 3 +photo/giraffe/084_0004.jpg 3 +photo/giraffe/084_0005.jpg 3 +photo/giraffe/084_0006.jpg 3 +photo/giraffe/084_0007.jpg 3 +photo/giraffe/084_0008.jpg 3 +photo/giraffe/084_0009.jpg 3 +photo/giraffe/084_0010.jpg 3 +photo/giraffe/084_0011.jpg 3 +photo/giraffe/084_0012.jpg 3 +photo/giraffe/084_0013.jpg 3 +photo/giraffe/084_0014.jpg 3 +photo/giraffe/084_0015.jpg 3 +photo/giraffe/084_0016.jpg 3 +photo/giraffe/084_0017.jpg 3 +photo/giraffe/084_0018.jpg 3 +photo/giraffe/084_0019.jpg 3 +photo/giraffe/084_0020.jpg 3 +photo/giraffe/084_0021.jpg 3 +photo/giraffe/084_0022.jpg 3 +photo/giraffe/084_0023.jpg 3 +photo/giraffe/084_0024.jpg 3 +photo/giraffe/084_0025.jpg 3 +photo/giraffe/084_0026.jpg 3 +photo/giraffe/084_0027.jpg 3 +photo/giraffe/084_0028.jpg 3 +photo/giraffe/084_0029.jpg 3 +photo/giraffe/084_0030.jpg 3 +photo/giraffe/084_0031.jpg 3 +photo/giraffe/084_0032.jpg 3 +photo/giraffe/084_0033.jpg 3 +photo/giraffe/084_0034.jpg 3 +photo/giraffe/084_0035.jpg 3 +photo/giraffe/084_0036.jpg 3 +photo/giraffe/084_0038.jpg 3 +photo/giraffe/084_0039.jpg 3 +photo/giraffe/084_0040.jpg 3 +photo/giraffe/084_0041.jpg 3 +photo/giraffe/084_0042.jpg 3 +photo/giraffe/084_0043.jpg 3 +photo/giraffe/084_0044.jpg 3 +photo/giraffe/084_0045.jpg 3 +photo/giraffe/084_0046.jpg 3 +photo/giraffe/084_0047.jpg 3 +photo/giraffe/084_0048.jpg 3 +photo/giraffe/084_0049.jpg 3 +photo/giraffe/084_0050.jpg 3 +photo/giraffe/084_0051.jpg 3 +photo/giraffe/084_0052.jpg 3 +photo/giraffe/084_0053.jpg 3 +photo/giraffe/084_0054.jpg 3 +photo/giraffe/084_0055.jpg 3 +photo/giraffe/084_0056.jpg 3 +photo/giraffe/084_0057.jpg 3 +photo/giraffe/084_0058.jpg 3 +photo/giraffe/084_0059.jpg 3 +photo/giraffe/084_0060.jpg 3 +photo/giraffe/084_0061.jpg 3 +photo/giraffe/084_0062.jpg 3 +photo/giraffe/084_0063.jpg 3 +photo/giraffe/084_0064.jpg 3 +photo/giraffe/084_0065.jpg 3 +photo/giraffe/084_0066.jpg 3 +photo/giraffe/084_0067.jpg 3 +photo/giraffe/084_0068.jpg 3 +photo/giraffe/084_0069.jpg 3 +photo/giraffe/084_0070.jpg 3 +photo/giraffe/084_0071.jpg 3 +photo/giraffe/084_0072.jpg 3 +photo/giraffe/084_0073.jpg 3 +photo/giraffe/084_0074.jpg 3 +photo/giraffe/084_0075.jpg 3 +photo/giraffe/084_0076.jpg 3 +photo/giraffe/084_0077.jpg 3 +photo/giraffe/084_0078.jpg 3 +photo/giraffe/084_0079.jpg 3 +photo/giraffe/084_0080.jpg 3 +photo/giraffe/084_0081.jpg 3 +photo/giraffe/084_0082.jpg 3 +photo/giraffe/084_0083.jpg 3 +photo/giraffe/084_0084.jpg 3 +photo/giraffe/n02439033_67.jpg 3 +photo/giraffe/n02439033_221.jpg 3 +photo/giraffe/n02439033_376.jpg 3 +photo/giraffe/n02439033_569.jpg 3 +photo/giraffe/n02439033_628.jpg 3 +photo/giraffe/n02439033_866.jpg 3 +photo/giraffe/n02439033_991.jpg 3 +photo/giraffe/n02439033_1327.jpg 3 +photo/giraffe/n02439033_1508.jpg 3 +photo/giraffe/n02439033_2486.jpg 3 +photo/giraffe/n02439033_2500.jpg 3 +photo/giraffe/n02439033_2677.jpg 3 +photo/giraffe/n02439033_3944.jpg 3 +photo/giraffe/n02439033_4601.jpg 3 +photo/giraffe/n02439033_5004.jpg 3 +photo/giraffe/n02439033_5652.jpg 3 +photo/giraffe/n02439033_6552.jpg 3 +photo/giraffe/n02439033_8789.jpg 3 +photo/giraffe/n02439033_8846.jpg 3 +photo/giraffe/n02439033_8875.jpg 3 +photo/giraffe/n02439033_9257.jpg 3 +photo/giraffe/n02439033_9261.jpg 3 +photo/giraffe/n02439033_9398.jpg 3 +photo/giraffe/n02439033_9472.jpg 3 +photo/giraffe/n02439033_9598.jpg 3 +photo/giraffe/n02439033_9604.jpg 3 +photo/giraffe/n02439033_9679.jpg 3 +photo/giraffe/n02439033_9719.jpg 3 +photo/giraffe/n02439033_10130.jpg 3 +photo/giraffe/n02439033_10164.jpg 3 +photo/giraffe/n02439033_10279.jpg 3 +photo/giraffe/n02439033_10295.jpg 3 +photo/giraffe/n02439033_10453.jpg 3 +photo/giraffe/n02439033_10491.jpg 3 +photo/giraffe/n02439033_10541.jpg 3 +photo/giraffe/n02439033_10616.jpg 3 +photo/giraffe/n02439033_10802.jpg 3 +photo/giraffe/n02439033_10803.jpg 3 +photo/giraffe/n02439033_10811.jpg 3 +photo/giraffe/n02439033_10839.jpg 3 +photo/giraffe/n02439033_10919.jpg 3 +photo/giraffe/n02439033_11059.jpg 3 +photo/giraffe/n02439033_11114.jpg 3 +photo/giraffe/n02439033_11130.jpg 3 +photo/giraffe/n02439033_11215.jpg 3 +photo/giraffe/n02439033_11273.jpg 3 +photo/giraffe/n02439033_11328.jpg 3 +photo/giraffe/n02439033_11458.jpg 3 +photo/giraffe/n02439033_11486.jpg 3 +photo/giraffe/n02439033_11487.jpg 3 +photo/giraffe/n02439033_11504.jpg 3 +photo/giraffe/n02439033_11599.jpg 3 +photo/giraffe/n02439033_11627.jpg 3 +photo/giraffe/n02439033_11666.jpg 3 +photo/giraffe/n02439033_11683.jpg 3 +photo/giraffe/n02439033_11715.jpg 3 +photo/giraffe/n02439033_11845.jpg 3 +photo/giraffe/n02439033_11894.jpg 3 +photo/giraffe/n02439033_12059.jpg 3 +photo/giraffe/n02439033_12413.jpg 3 +photo/giraffe/n02439033_12485.jpg 3 +photo/giraffe/n02439033_12680.jpg 3 +photo/giraffe/n02439033_12930.jpg 3 +photo/giraffe/n02439033_12939.jpg 3 +photo/giraffe/n02439033_12987.jpg 3 +photo/giraffe/n02439033_13236.jpg 3 +photo/giraffe/n02439033_13384.jpg 3 +photo/giraffe/n02439033_13430.jpg 3 +photo/giraffe/n02439033_13602.jpg 3 +photo/giraffe/n02439033_13868.jpg 3 +photo/giraffe/n02439033_14040.jpg 3 +photo/giraffe/n02439033_14060.jpg 3 +photo/giraffe/n02439033_14121.jpg 3 +photo/giraffe/n02439033_14148.jpg 3 +photo/giraffe/n02439033_14184.jpg 3 +photo/giraffe/n02439033_14322.jpg 3 +photo/giraffe/n02439033_14497.jpg 3 +photo/giraffe/n02439033_14554.jpg 3 +photo/giraffe/n02439033_14580.jpg 3 +photo/giraffe/n02439033_14600.jpg 3 +photo/giraffe/n02439033_14609.jpg 3 +photo/giraffe/n02439033_14724.jpg 3 +photo/giraffe/n02439033_14764.jpg 3 +photo/giraffe/n02439033_14781.jpg 3 +photo/giraffe/n02439033_14784.jpg 3 +photo/giraffe/n02439033_14846.jpg 3 +photo/giraffe/n02439033_14872.jpg 3 +photo/giraffe/n02439033_14962.jpg 3 +photo/giraffe/n02439033_15005.jpg 3 +photo/giraffe/n02439033_15384.jpg 3 +photo/giraffe/n02439033_15401.jpg 3 +photo/giraffe/n02439033_15453.jpg 3 +photo/giraffe/n02439033_15479.jpg 3 +photo/giraffe/n02439033_15540.jpg 3 +photo/giraffe/n02439033_15555.jpg 3 +photo/giraffe/n02439033_15936.jpg 3 +photo/giraffe/n02439033_16085.jpg 3 +photo/giraffe/n02439033_16356.jpg 3 +photo/giraffe/n02439033_16483.jpg 3 +photo/guitar/063_0001.jpg 4 +photo/guitar/063_0002.jpg 4 +photo/guitar/063_0003.jpg 4 +photo/guitar/063_0004.jpg 4 +photo/guitar/063_0005.jpg 4 +photo/guitar/063_0006.jpg 4 +photo/guitar/063_0007.jpg 4 +photo/guitar/063_0008.jpg 4 +photo/guitar/063_0009.jpg 4 +photo/guitar/063_0010.jpg 4 +photo/guitar/063_0012.jpg 4 +photo/guitar/063_0013.jpg 4 +photo/guitar/063_0016.jpg 4 +photo/guitar/063_0018.jpg 4 +photo/guitar/063_0019.jpg 4 +photo/guitar/063_0020.jpg 4 +photo/guitar/063_0021.jpg 4 +photo/guitar/063_0022.jpg 4 +photo/guitar/063_0023.jpg 4 +photo/guitar/063_0024.jpg 4 +photo/guitar/063_0025.jpg 4 +photo/guitar/063_0026.jpg 4 +photo/guitar/063_0027.jpg 4 +photo/guitar/063_0028.jpg 4 +photo/guitar/063_0029.jpg 4 +photo/guitar/063_0030.jpg 4 +photo/guitar/063_0031.jpg 4 +photo/guitar/063_0032.jpg 4 +photo/guitar/063_0035.jpg 4 +photo/guitar/063_0036.jpg 4 +photo/guitar/063_0037.jpg 4 +photo/guitar/063_0038.jpg 4 +photo/guitar/063_0039.jpg 4 +photo/guitar/063_0040.jpg 4 +photo/guitar/063_0041.jpg 4 +photo/guitar/063_0042.jpg 4 +photo/guitar/063_0043.jpg 4 +photo/guitar/063_0045.jpg 4 +photo/guitar/063_0046.jpg 4 +photo/guitar/063_0047.jpg 4 +photo/guitar/063_0048.jpg 4 +photo/guitar/063_0049.jpg 4 +photo/guitar/063_0050.jpg 4 +photo/guitar/063_0051.jpg 4 +photo/guitar/063_0052.jpg 4 +photo/guitar/063_0053.jpg 4 +photo/guitar/063_0054.jpg 4 +photo/guitar/063_0055.jpg 4 +photo/guitar/063_0056.jpg 4 +photo/guitar/063_0059.jpg 4 +photo/guitar/063_0061.jpg 4 +photo/guitar/063_0062.jpg 4 +photo/guitar/063_0065.jpg 4 +photo/guitar/063_0067.jpg 4 +photo/guitar/063_0068.jpg 4 +photo/guitar/063_0069.jpg 4 +photo/guitar/063_0071.jpg 4 +photo/guitar/063_0072.jpg 4 +photo/guitar/063_0073.jpg 4 +photo/guitar/063_0074.jpg 4 +photo/guitar/063_0075.jpg 4 +photo/guitar/063_0076.jpg 4 +photo/guitar/063_0077.jpg 4 +photo/guitar/063_0078.jpg 4 +photo/guitar/063_0079.jpg 4 +photo/guitar/063_0080.jpg 4 +photo/guitar/063_0081.jpg 4 +photo/guitar/063_0082.jpg 4 +photo/guitar/063_0084.jpg 4 +photo/guitar/063_0085.jpg 4 +photo/guitar/063_0086.jpg 4 +photo/guitar/063_0087.jpg 4 +photo/guitar/063_0088.jpg 4 +photo/guitar/063_0089.jpg 4 +photo/guitar/063_0090.jpg 4 +photo/guitar/063_0091.jpg 4 +photo/guitar/063_0092.jpg 4 +photo/guitar/063_0093.jpg 4 +photo/guitar/063_0094.jpg 4 +photo/guitar/063_0095.jpg 4 +photo/guitar/063_0096.jpg 4 +photo/guitar/063_0097.jpg 4 +photo/guitar/063_0098.jpg 4 +photo/guitar/063_0099.jpg 4 +photo/guitar/063_0100.jpg 4 +photo/guitar/063_0101.jpg 4 +photo/guitar/063_0102.jpg 4 +photo/guitar/063_0103.jpg 4 +photo/guitar/063_0104.jpg 4 +photo/guitar/063_0105.jpg 4 +photo/guitar/063_0106.jpg 4 +photo/guitar/063_0107.jpg 4 +photo/guitar/063_0108.jpg 4 +photo/guitar/063_0109.jpg 4 +photo/guitar/063_0110.jpg 4 +photo/guitar/063_0111.jpg 4 +photo/guitar/063_0112.jpg 4 +photo/guitar/063_0113.jpg 4 +photo/guitar/063_0114.jpg 4 +photo/guitar/063_0115.jpg 4 +photo/guitar/063_0116.jpg 4 +photo/guitar/063_0117.jpg 4 +photo/guitar/063_0118.jpg 4 +photo/guitar/063_0119.jpg 4 +photo/guitar/063_0120.jpg 4 +photo/guitar/063_0121.jpg 4 +photo/guitar/063_0122.jpg 4 +photo/guitar/n02676566_307.jpg 4 +photo/guitar/n02676566_330.jpg 4 +photo/guitar/n02676566_659.jpg 4 +photo/guitar/n02676566_1324.jpg 4 +photo/guitar/n02676566_2380.jpg 4 +photo/guitar/n02676566_3360.jpg 4 +photo/guitar/n02676566_4058.jpg 4 +photo/guitar/n02676566_4189.jpg 4 +photo/guitar/n02676566_4469.jpg 4 +photo/guitar/n02676566_4605.jpg 4 +photo/guitar/n02676566_4699.jpg 4 +photo/guitar/n02676566_5489.jpg 4 +photo/guitar/n02676566_5735.jpg 4 +photo/guitar/n02676566_6150.jpg 4 +photo/guitar/n02676566_6402.jpg 4 +photo/guitar/n02676566_6430.jpg 4 +photo/guitar/n02676566_6560.jpg 4 +photo/guitar/n02676566_6631.jpg 4 +photo/guitar/n02676566_6704.jpg 4 +photo/guitar/n02676566_6914.jpg 4 +photo/guitar/n02676566_6948.jpg 4 +photo/guitar/n02676566_7385.jpg 4 +photo/guitar/n02676566_7770.jpg 4 +photo/guitar/n02676566_7830.jpg 4 +photo/guitar/n02676566_7844.jpg 4 +photo/guitar/n02676566_7927.jpg 4 +photo/guitar/n02676566_8268.jpg 4 +photo/guitar/n02676566_8309.jpg 4 +photo/guitar/n02676566_8467.jpg 4 +photo/guitar/n02676566_8618.jpg 4 +photo/guitar/n02676566_8820.jpg 4 +photo/guitar/n02676566_8859.jpg 4 +photo/guitar/n02676566_8997.jpg 4 +photo/guitar/n02676566_9062.jpg 4 +photo/guitar/n02676566_9243.jpg 4 +photo/guitar/n02676566_9254.jpg 4 +photo/guitar/n02676566_9451.jpg 4 +photo/guitar/n02676566_9577.jpg 4 +photo/guitar/n02676566_9661.jpg 4 +photo/guitar/n02676566_9936.jpg 4 +photo/guitar/n02676566_11573.jpg 4 +photo/guitar/n02676566_12344.jpg 4 +photo/guitar/n03272010_392.jpg 4 +photo/guitar/n03272010_446.jpg 4 +photo/guitar/n03272010_1708.jpg 4 +photo/guitar/n03272010_3732.jpg 4 +photo/guitar/n03272010_5483.jpg 4 +photo/guitar/n03272010_5887.jpg 4 +photo/guitar/n03272010_6255.jpg 4 +photo/guitar/n03272010_6291.jpg 4 +photo/guitar/n03272010_6662.jpg 4 +photo/guitar/n03272010_6727.jpg 4 +photo/guitar/n03272010_6737.jpg 4 +photo/guitar/n03272010_6799.jpg 4 +photo/guitar/n03272010_6809.jpg 4 +photo/guitar/n03272010_6820.jpg 4 +photo/guitar/n03272010_6926.jpg 4 +photo/guitar/n03272010_7092.jpg 4 +photo/guitar/n03272010_7390.jpg 4 +photo/guitar/n03272010_7729.jpg 4 +photo/guitar/n03272010_9557.jpg 4 +photo/guitar/n03272010_9858.jpg 4 +photo/guitar/n03272010_9899.jpg 4 +photo/guitar/n03272010_10441.jpg 4 +photo/guitar/n03272010_10795.jpg 4 +photo/guitar/n03272010_12151.jpg 4 +photo/guitar/n03272010_12468.jpg 4 +photo/guitar/n03467517_6423.jpg 4 +photo/guitar/n03467517_7007.jpg 4 +photo/guitar/n03467517_8929.jpg 4 +photo/guitar/n03467517_11020.jpg 4 +photo/guitar/n03467517_12925.jpg 4 +photo/guitar/n03467517_17233.jpg 4 +photo/guitar/n03467517_19701.jpg 4 +photo/guitar/n03467517_21884.jpg 4 +photo/guitar/n03467517_22246.jpg 4 +photo/guitar/n03467517_22785.jpg 4 +photo/guitar/n03467517_23229.jpg 4 +photo/guitar/n03467517_24525.jpg 4 +photo/horse/105_0002.jpg 5 +photo/horse/105_0003.jpg 5 +photo/horse/105_0007.jpg 5 +photo/horse/105_0008.jpg 5 +photo/horse/105_0009.jpg 5 +photo/horse/105_0010.jpg 5 +photo/horse/105_0012.jpg 5 +photo/horse/105_0013.jpg 5 +photo/horse/105_0018.jpg 5 +photo/horse/105_0022.jpg 5 +photo/horse/105_0025.jpg 5 +photo/horse/105_0028.jpg 5 +photo/horse/105_0029.jpg 5 +photo/horse/105_0030.jpg 5 +photo/horse/105_0033.jpg 5 +photo/horse/105_0037.jpg 5 +photo/horse/105_0038.jpg 5 +photo/horse/105_0041.jpg 5 +photo/horse/105_0042.jpg 5 +photo/horse/105_0047.jpg 5 +photo/horse/105_0048.jpg 5 +photo/horse/105_0050.jpg 5 +photo/horse/105_0053.jpg 5 +photo/horse/105_0056.jpg 5 +photo/horse/105_0058.jpg 5 +photo/horse/105_0059.jpg 5 +photo/horse/105_0063.jpg 5 +photo/horse/105_0066.jpg 5 +photo/horse/105_0067.jpg 5 +photo/horse/105_0070.jpg 5 +photo/horse/105_0071.jpg 5 +photo/horse/105_0072.jpg 5 +photo/horse/105_0073.jpg 5 +photo/horse/105_0074.jpg 5 +photo/horse/105_0075.jpg 5 +photo/horse/105_0076.jpg 5 +photo/horse/105_0077.jpg 5 +photo/horse/105_0081.jpg 5 +photo/horse/105_0083.jpg 5 +photo/horse/105_0084.jpg 5 +photo/horse/105_0086.jpg 5 +photo/horse/105_0088.jpg 5 +photo/horse/105_0089.jpg 5 +photo/horse/105_0090.jpg 5 +photo/horse/105_0091.jpg 5 +photo/horse/105_0092.jpg 5 +photo/horse/105_0099.jpg 5 +photo/horse/105_0101.jpg 5 +photo/horse/105_0103.jpg 5 +photo/horse/105_0104.jpg 5 +photo/horse/105_0105.jpg 5 +photo/horse/105_0106.jpg 5 +photo/horse/105_0108.jpg 5 +photo/horse/105_0109.jpg 5 +photo/horse/105_0111.jpg 5 +photo/horse/105_0115.jpg 5 +photo/horse/105_0116.jpg 5 +photo/horse/105_0118.jpg 5 +photo/horse/105_0120.jpg 5 +photo/horse/105_0121.jpg 5 +photo/horse/105_0123.jpg 5 +photo/horse/105_0124.jpg 5 +photo/horse/105_0125.jpg 5 +photo/horse/105_0130.jpg 5 +photo/horse/105_0131.jpg 5 +photo/horse/105_0134.jpg 5 +photo/horse/105_0135.jpg 5 +photo/horse/105_0137.jpg 5 +photo/horse/105_0138.jpg 5 +photo/horse/105_0139.jpg 5 +photo/horse/105_0140.jpg 5 +photo/horse/105_0143.jpg 5 +photo/horse/105_0146.jpg 5 +photo/horse/105_0147.jpg 5 +photo/horse/105_0149.jpg 5 +photo/horse/105_0150.jpg 5 +photo/horse/105_0154.jpg 5 +photo/horse/105_0156.jpg 5 +photo/horse/105_0157.jpg 5 +photo/horse/105_0161.jpg 5 +photo/horse/105_0164.jpg 5 +photo/horse/105_0165.jpg 5 +photo/horse/105_0172.jpg 5 +photo/horse/105_0173.jpg 5 +photo/horse/105_0174.jpg 5 +photo/horse/105_0175.jpg 5 +photo/horse/105_0176.jpg 5 +photo/horse/105_0177.jpg 5 +photo/horse/105_0180.jpg 5 +photo/horse/105_0181.jpg 5 +photo/horse/105_0182.jpg 5 +photo/horse/105_0183.jpg 5 +photo/horse/105_0184.jpg 5 +photo/horse/105_0185.jpg 5 +photo/horse/105_0193.jpg 5 +photo/horse/105_0194.jpg 5 +photo/horse/105_0196.jpg 5 +photo/horse/105_0199.jpg 5 +photo/horse/105_0203.jpg 5 +photo/horse/105_0205.jpg 5 +photo/horse/105_0206.jpg 5 +photo/horse/105_0207.jpg 5 +photo/horse/105_0208.jpg 5 +photo/horse/105_0210.jpg 5 +photo/horse/105_0215.jpg 5 +photo/horse/105_0223.jpg 5 +photo/horse/105_0229.jpg 5 +photo/horse/105_0230.jpg 5 +photo/horse/105_0232.jpg 5 +photo/horse/105_0236.jpg 5 +photo/horse/105_0240.jpg 5 +photo/horse/105_0241.jpg 5 +photo/horse/105_0249.jpg 5 +photo/horse/105_0253.jpg 5 +photo/horse/105_0255.jpg 5 +photo/horse/105_0257.jpg 5 +photo/horse/105_0260.jpg 5 +photo/horse/105_0264.jpg 5 +photo/horse/105_0265.jpg 5 +photo/horse/105_0266.jpg 5 +photo/horse/105_0269.jpg 5 +photo/horse/105_0270.jpg 5 +photo/horse/n02374451_54.jpg 5 +photo/horse/n02374451_245.jpg 5 +photo/horse/n02374451_257.jpg 5 +photo/horse/n02374451_262.jpg 5 +photo/horse/n02374451_388.jpg 5 +photo/horse/n02374451_468.jpg 5 +photo/horse/n02374451_490.jpg 5 +photo/horse/n02374451_503.jpg 5 +photo/horse/n02374451_597.jpg 5 +photo/horse/n02374451_777.jpg 5 +photo/horse/n02374451_779.jpg 5 +photo/horse/n02374451_916.jpg 5 +photo/horse/n02374451_925.jpg 5 +photo/horse/n02374451_929.jpg 5 +photo/horse/n02374451_1189.jpg 5 +photo/horse/n02374451_1234.jpg 5 +photo/horse/n02374451_1443.jpg 5 +photo/horse/n02374451_2248.jpg 5 +photo/horse/n02374451_2372.jpg 5 +photo/horse/n02374451_2478.jpg 5 +photo/horse/n02374451_2616.jpg 5 +photo/horse/n02374451_2733.jpg 5 +photo/horse/n02374451_2743.jpg 5 +photo/horse/n02374451_2825.jpg 5 +photo/horse/n02374451_3388.jpg 5 +photo/horse/n02374451_4538.jpg 5 +photo/horse/n02374451_4553.jpg 5 +photo/horse/n02374451_4795.jpg 5 +photo/horse/n02374451_4818.jpg 5 +photo/horse/n02374451_4963.jpg 5 +photo/horse/n02374451_6192.jpg 5 +photo/horse/n02374451_7631.jpg 5 +photo/horse/n02374451_8065.jpg 5 +photo/horse/n02374451_8526.jpg 5 +photo/horse/n02374451_8718.jpg 5 +photo/horse/n02374451_8744.jpg 5 +photo/horse/n02374451_9064.jpg 5 +photo/horse/n02374451_9443.jpg 5 +photo/horse/n02374451_9892.jpg 5 +photo/horse/n02374451_10081.jpg 5 +photo/horse/n02374451_10098.jpg 5 +photo/horse/n02374451_10331.jpg 5 +photo/horse/n02374451_10669.jpg 5 +photo/horse/n02374451_10761.jpg 5 +photo/horse/n02374451_10809.jpg 5 +photo/horse/n02374451_11479.jpg 5 +photo/horse/n02374451_11483.jpg 5 +photo/horse/n02374451_11492.jpg 5 +photo/horse/n02374451_11894.jpg 5 +photo/horse/n02374451_12128.jpg 5 +photo/horse/n02374451_12174.jpg 5 +photo/horse/n02374451_12225.jpg 5 +photo/horse/n02374451_12230.jpg 5 +photo/horse/n02374451_12250.jpg 5 +photo/horse/n02374451_12254.jpg 5 +photo/horse/n02374451_12418.jpg 5 +photo/horse/n02374451_12792.jpg 5 +photo/horse/n02374451_12847.jpg 5 +photo/horse/n02374451_13159.jpg 5 +photo/horse/n02374451_13718.jpg 5 +photo/horse/n02374451_14119.jpg 5 +photo/horse/n02374451_14233.jpg 5 +photo/horse/n02374451_14399.jpg 5 +photo/horse/n02374451_14425.jpg 5 +photo/horse/n02374451_14738.jpg 5 +photo/horse/n02374451_14846.jpg 5 +photo/horse/n02374451_15307.jpg 5 +photo/horse/n02374451_15440.jpg 5 +photo/horse/n02374451_15453.jpg 5 +photo/horse/n02374451_15669.jpg 5 +photo/horse/n02374451_16358.jpg 5 +photo/horse/n02374451_17384.jpg 5 +photo/horse/n02374451_17474.jpg 5 +photo/horse/n02374451_17634.jpg 5 +photo/horse/n02374451_18192.jpg 5 +photo/horse/n02374451_18570.jpg 5 +photo/horse/n02374451_18909.jpg 5 +photo/house/pic_010.jpg 6 +photo/house/pic_011.jpg 6 +photo/house/pic_012.jpg 6 +photo/house/pic_013.jpg 6 +photo/house/pic_014.jpg 6 +photo/house/pic_015.jpg 6 +photo/house/pic_016.jpg 6 +photo/house/pic_017.jpg 6 +photo/house/pic_018.jpg 6 +photo/house/pic_021.jpg 6 +photo/house/pic_019.jpg 6 +photo/house/pic_022.jpg 6 +photo/house/pic_020.jpg 6 +photo/house/pic_023.jpg 6 +photo/house/pic_024.jpg 6 +photo/house/pic_026.jpg 6 +photo/house/pic_025.jpg 6 +photo/house/pic_027.jpg 6 +photo/house/pic_028.jpg 6 +photo/house/pic_029.jpg 6 +photo/house/pic_031.jpg 6 +photo/house/pic_239.jpg 6 +photo/house/pic_240.jpg 6 +photo/house/pic_241.jpg 6 +photo/house/pic_242.jpg 6 +photo/house/pic_248.jpg 6 +photo/house/pic_246.jpg 6 +photo/house/pic_247.jpg 6 +photo/house/pic_244.jpg 6 +photo/house/pic_243.jpg 6 +photo/house/pic_250.jpg 6 +photo/house/pic_249.jpg 6 +photo/house/pic_251.jpg 6 +photo/house/pic_252.jpg 6 +photo/house/pic_253.jpg 6 +photo/house/pic_256.jpg 6 +photo/house/pic_255.jpg 6 +photo/house/pic_257.jpg 6 +photo/house/pic_260.jpg 6 +photo/house/pic_032.jpg 6 +photo/house/pic_030.jpg 6 +photo/house/pic_033.jpg 6 +photo/house/pic_034.jpg 6 +photo/house/pic_035.jpg 6 +photo/house/pic_036.jpg 6 +photo/house/pic_037.jpg 6 +photo/house/pic_038.jpg 6 +photo/house/pic_039.jpg 6 +photo/house/pic_042.jpg 6 +photo/house/pic_041.jpg 6 +photo/house/pic_040.jpg 6 +photo/house/pic_045.jpg 6 +photo/house/pic_046.jpg 6 +photo/house/pic_044.jpg 6 +photo/house/pic_043.jpg 6 +photo/house/pic_047.jpg 6 +photo/house/pic_048.jpg 6 +photo/house/pic_049.jpg 6 +photo/house/pic_050.jpg 6 +photo/house/pic_058.jpg 6 +photo/house/pic_216.jpg 6 +photo/house/pic_217.jpg 6 +photo/house/pic_220.jpg 6 +photo/house/pic_221.jpg 6 +photo/house/pic_222.jpg 6 +photo/house/pic_223.jpg 6 +photo/house/pic_224.jpg 6 +photo/house/pic_225.jpg 6 +photo/house/pic_226.jpg 6 +photo/house/pic_228.jpg 6 +photo/house/pic_229.jpg 6 +photo/house/pic_230.jpg 6 +photo/house/pic_231.jpg 6 +photo/house/pic_232.jpg 6 +photo/house/pic_233.jpg 6 +photo/house/pic_234.jpg 6 +photo/house/pic_235.jpg 6 +photo/house/pic_236.jpg 6 +photo/house/pic_238.jpg 6 +photo/house/pic_237.jpg 6 +photo/house/pic_067.jpg 6 +photo/house/pic_062.jpg 6 +photo/house/pic_075.jpg 6 +photo/house/pic_078.jpg 6 +photo/house/pic_079.jpg 6 +photo/house/pic_070.jpg 6 +photo/house/pic_066.jpg 6 +photo/house/pic_088.jpg 6 +photo/house/pic_081.jpg 6 +photo/house/pic_091.jpg 6 +photo/house/pic_072.jpg 6 +photo/house/pic_093.jpg 6 +photo/house/pic_086.jpg 6 +photo/house/pic_098.jpg 6 +photo/house/pic_096.jpg 6 +photo/house/pic_095.jpg 6 +photo/house/pic_094.jpg 6 +photo/house/pic_092.jpg 6 +photo/house/pic_090.jpg 6 +photo/house/pic_097.jpg 6 +photo/house/pic_061.jpg 6 +photo/house/pic_060.jpg 6 +photo/house/pic_057.jpg 6 +photo/house/pic_051.jpg 6 +photo/house/pic_054.jpg 6 +photo/house/pic_053.jpg 6 +photo/house/pic_052.jpg 6 +photo/house/pic_063.jpg 6 +photo/house/pic_059.jpg 6 +photo/house/pic_055.jpg 6 +photo/house/pic_056.jpg 6 +photo/house/pic_082.jpg 6 +photo/house/pic_080.jpg 6 +photo/house/pic_077.jpg 6 +photo/house/pic_076.jpg 6 +photo/house/pic_074.jpg 6 +photo/house/pic_073.jpg 6 +photo/house/pic_071.jpg 6 +photo/house/pic_069.jpg 6 +photo/house/pic_068.jpg 6 +photo/house/pic_065.jpg 6 +photo/house/pic_153.jpg 6 +photo/house/pic_156.jpg 6 +photo/house/pic_157.jpg 6 +photo/house/pic_158.jpg 6 +photo/house/pic_159.jpg 6 +photo/house/pic_160.jpg 6 +photo/house/pic_162.jpg 6 +photo/house/pic_161.jpg 6 +photo/house/pic_166.jpg 6 +photo/house/pic_165.jpg 6 +photo/house/pic_163.jpg 6 +photo/house/pic_164.jpg 6 +photo/house/pic_167.jpg 6 +photo/house/pic_168.jpg 6 +photo/house/pic_170.jpg 6 +photo/house/pic_169.jpg 6 +photo/house/pic_171.jpg 6 +photo/house/pic_172.jpg 6 +photo/house/pic_174.jpg 6 +photo/house/pic_175.jpg 6 +photo/house/pic_173.jpg 6 +photo/house/pic_134.jpg 6 +photo/house/pic_135.jpg 6 +photo/house/pic_136.jpg 6 +photo/house/pic_138.jpg 6 +photo/house/pic_139.jpg 6 +photo/house/pic_137.jpg 6 +photo/house/pic_140.jpg 6 +photo/house/pic_141.jpg 6 +photo/house/pic_143.jpg 6 +photo/house/pic_142.jpg 6 +photo/house/pic_144.jpg 6 +photo/house/pic_146.jpg 6 +photo/house/pic_145.jpg 6 +photo/house/pic_147.jpg 6 +photo/house/pic_148.jpg 6 +photo/house/pic_149.jpg 6 +photo/house/pic_150.jpg 6 +photo/house/pic_151.jpg 6 +photo/house/pic_154.jpg 6 +photo/house/pic_155.jpg 6 +photo/house/pic_197.jpg 6 +photo/house/pic_199.jpg 6 +photo/house/pic_200.jpg 6 +photo/house/pic_198.jpg 6 +photo/house/pic_202.jpg 6 +photo/house/pic_201.jpg 6 +photo/house/pic_204.jpg 6 +photo/house/pic_205.jpg 6 +photo/house/pic_203.jpg 6 +photo/house/pic_207.jpg 6 +photo/house/pic_206.jpg 6 +photo/house/pic_209.jpg 6 +photo/house/pic_208.jpg 6 +photo/house/pic_210.jpg 6 +photo/house/pic_211.jpg 6 +photo/house/pic_214.jpg 6 +photo/house/pic_213.jpg 6 +photo/house/pic_215.jpg 6 +photo/house/pic_219.jpg 6 +photo/house/pic_218.jpg 6 +photo/house/pic_280.jpg 6 +photo/house/pic_276.jpg 6 +photo/house/pic_287.jpg 6 +photo/house/pic_282.jpg 6 +photo/house/pic_283.jpg 6 +photo/house/pic_288.jpg 6 +photo/house/pic_289.jpg 6 +photo/house/pic_290.jpg 6 +photo/house/pic_281.jpg 6 +photo/house/pic_284.jpg 6 +photo/house/pic_089.jpg 6 +photo/house/pic_084.jpg 6 +photo/house/pic_085.jpg 6 +photo/house/pic_083.jpg 6 +photo/house/pic_099.jpg 6 +photo/house/pic_087.jpg 6 +photo/house/pic_106.jpg 6 +photo/house/pic_104.jpg 6 +photo/house/pic_103.jpg 6 +photo/house/pic_102.jpg 6 +photo/house/pic_101.jpg 6 +photo/house/pic_100.jpg 6 +photo/house/pic_110.jpg 6 +photo/house/pic_109.jpg 6 +photo/house/pic_108.jpg 6 +photo/house/pic_107.jpg 6 +photo/house/pic_111.jpg 6 +photo/house/pic_112.jpg 6 +photo/house/pic_113.jpg 6 +photo/house/pic_114.jpg 6 +photo/house/pic_262.jpg 6 +photo/house/pic_259.jpg 6 +photo/house/pic_264.jpg 6 +photo/house/pic_263.jpg 6 +photo/house/pic_265.jpg 6 +photo/house/pic_261.jpg 6 +photo/house/pic_266.jpg 6 +photo/house/pic_267.jpg 6 +photo/house/pic_269.jpg 6 +photo/house/pic_270.jpg 6 +photo/house/pic_268.jpg 6 +photo/house/pic_279.jpg 6 +photo/house/pic_278.jpg 6 +photo/house/pic_277.jpg 6 +photo/house/pic_275.jpg 6 +photo/house/pic_272.jpg 6 +photo/house/pic_274.jpg 6 +photo/house/pic_273.jpg 6 +photo/house/pic_271.jpg 6 +photo/house/pic_286.jpg 6 +photo/house/pic_285.jpg 6 +photo/house/pic_116.jpg 6 +photo/house/pic_115.jpg 6 +photo/house/pic_117.jpg 6 +photo/house/pic_118.jpg 6 +photo/house/pic_120.jpg 6 +photo/house/pic_119.jpg 6 +photo/house/pic_121.jpg 6 +photo/house/pic_122.jpg 6 +photo/house/pic_124.jpg 6 +photo/house/pic_123.jpg 6 +photo/house/pic_125.jpg 6 +photo/house/pic_126.jpg 6 +photo/house/pic_127.jpg 6 +photo/house/pic_128.jpg 6 +photo/house/pic_129.jpg 6 +photo/house/pic_130.jpg 6 +photo/house/pic_131.jpg 6 +photo/house/pic_132.jpg 6 +photo/house/pic_133.jpg 6 +photo/house/pic_001.jpg 6 +photo/house/pic_002.jpg 6 +photo/house/pic_003.jpg 6 +photo/house/pic_004.jpg 6 +photo/house/pic_005.jpg 6 +photo/house/pic_006.jpg 6 +photo/house/pic_007.jpg 6 +photo/house/pic_008.jpg 6 +photo/house/pic_178.jpg 6 +photo/house/pic_177.jpg 6 +photo/house/pic_176.jpg 6 +photo/house/pic_179.jpg 6 +photo/house/pic_181.jpg 6 +photo/house/pic_180.jpg 6 +photo/house/pic_185.jpg 6 +photo/house/pic_183.jpg 6 +photo/house/pic_184.jpg 6 +photo/house/pic_190.jpg 6 +photo/house/pic_188.jpg 6 +photo/house/pic_189.jpg 6 +photo/house/pic_186.jpg 6 +photo/house/pic_187.jpg 6 +photo/house/pic_191.jpg 6 +photo/house/pic_192.jpg 6 +photo/house/pic_194.jpg 6 +photo/house/pic_193.jpg 6 +photo/house/pic_195.jpg 6 +photo/house/pic_196.jpg 6 +photo/person/253_0001.jpg 7 +photo/person/253_0002.jpg 7 +photo/person/253_0003.jpg 7 +photo/person/253_0004.jpg 7 +photo/person/253_0005.jpg 7 +photo/person/253_0006.jpg 7 +photo/person/253_0007.jpg 7 +photo/person/253_0008.jpg 7 +photo/person/253_0009.jpg 7 +photo/person/253_0010.jpg 7 +photo/person/253_0011.jpg 7 +photo/person/253_0012.jpg 7 +photo/person/253_0013.jpg 7 +photo/person/253_0014.jpg 7 +photo/person/253_0015.jpg 7 +photo/person/253_0016.jpg 7 +photo/person/253_0017.jpg 7 +photo/person/253_0018.jpg 7 +photo/person/253_0019.jpg 7 +photo/person/253_0020.jpg 7 +photo/person/253_0021.jpg 7 +photo/person/253_0022.jpg 7 +photo/person/253_0023.jpg 7 +photo/person/253_0024.jpg 7 +photo/person/253_0025.jpg 7 +photo/person/253_0026.jpg 7 +photo/person/253_0027.jpg 7 +photo/person/253_0028.jpg 7 +photo/person/253_0029.jpg 7 +photo/person/253_0030.jpg 7 +photo/person/253_0031.jpg 7 +photo/person/253_0032.jpg 7 +photo/person/253_0033.jpg 7 +photo/person/253_0034.jpg 7 +photo/person/253_0035.jpg 7 +photo/person/253_0036.jpg 7 +photo/person/253_0037.jpg 7 +photo/person/253_0038.jpg 7 +photo/person/253_0039.jpg 7 +photo/person/253_0040.jpg 7 +photo/person/253_0041.jpg 7 +photo/person/253_0042.jpg 7 +photo/person/253_0043.jpg 7 +photo/person/253_0044.jpg 7 +photo/person/253_0045.jpg 7 +photo/person/253_0046.jpg 7 +photo/person/253_0047.jpg 7 +photo/person/253_0048.jpg 7 +photo/person/253_0049.jpg 7 +photo/person/253_0050.jpg 7 +photo/person/253_0051.jpg 7 +photo/person/253_0052.jpg 7 +photo/person/253_0053.jpg 7 +photo/person/253_0054.jpg 7 +photo/person/253_0055.jpg 7 +photo/person/253_0056.jpg 7 +photo/person/253_0057.jpg 7 +photo/person/253_0058.jpg 7 +photo/person/253_0059.jpg 7 +photo/person/253_0060.jpg 7 +photo/person/253_0061.jpg 7 +photo/person/253_0062.jpg 7 +photo/person/253_0063.jpg 7 +photo/person/253_0064.jpg 7 +photo/person/253_0065.jpg 7 +photo/person/253_0066.jpg 7 +photo/person/253_0067.jpg 7 +photo/person/253_0068.jpg 7 +photo/person/253_0069.jpg 7 +photo/person/253_0070.jpg 7 +photo/person/253_0071.jpg 7 +photo/person/253_0072.jpg 7 +photo/person/253_0073.jpg 7 +photo/person/253_0074.jpg 7 +photo/person/253_0075.jpg 7 +photo/person/253_0076.jpg 7 +photo/person/253_0077.jpg 7 +photo/person/253_0078.jpg 7 +photo/person/253_0079.jpg 7 +photo/person/253_0080.jpg 7 +photo/person/253_0081.jpg 7 +photo/person/253_0082.jpg 7 +photo/person/253_0083.jpg 7 +photo/person/253_0084.jpg 7 +photo/person/253_0085.jpg 7 +photo/person/253_0086.jpg 7 +photo/person/253_0087.jpg 7 +photo/person/253_0088.jpg 7 +photo/person/253_0089.jpg 7 +photo/person/253_0090.jpg 7 +photo/person/253_0091.jpg 7 +photo/person/253_0092.jpg 7 +photo/person/253_0093.jpg 7 +photo/person/253_0094.jpg 7 +photo/person/253_0095.jpg 7 +photo/person/253_0096.jpg 7 +photo/person/253_0097.jpg 7 +photo/person/253_0098.jpg 7 +photo/person/253_0099.jpg 7 +photo/person/253_0100.jpg 7 +photo/person/253_0101.jpg 7 +photo/person/253_0102.jpg 7 +photo/person/253_0103.jpg 7 +photo/person/253_0104.jpg 7 +photo/person/253_0105.jpg 7 +photo/person/253_0106.jpg 7 +photo/person/253_0107.jpg 7 +photo/person/253_0108.jpg 7 +photo/person/253_0109.jpg 7 +photo/person/253_0110.jpg 7 +photo/person/253_0111.jpg 7 +photo/person/253_0112.jpg 7 +photo/person/253_0113.jpg 7 +photo/person/253_0114.jpg 7 +photo/person/253_0115.jpg 7 +photo/person/253_0116.jpg 7 +photo/person/253_0117.jpg 7 +photo/person/253_0118.jpg 7 +photo/person/253_0119.jpg 7 +photo/person/253_0120.jpg 7 +photo/person/253_0121.jpg 7 +photo/person/253_0122.jpg 7 +photo/person/253_0123.jpg 7 +photo/person/253_0124.jpg 7 +photo/person/253_0125.jpg 7 +photo/person/253_0126.jpg 7 +photo/person/253_0127.jpg 7 +photo/person/253_0128.jpg 7 +photo/person/253_0129.jpg 7 +photo/person/253_0130.jpg 7 +photo/person/253_0131.jpg 7 +photo/person/253_0132.jpg 7 +photo/person/253_0133.jpg 7 +photo/person/253_0134.jpg 7 +photo/person/253_0135.jpg 7 +photo/person/253_0136.jpg 7 +photo/person/253_0137.jpg 7 +photo/person/253_0138.jpg 7 +photo/person/253_0139.jpg 7 +photo/person/253_0140.jpg 7 +photo/person/253_0141.jpg 7 +photo/person/253_0142.jpg 7 +photo/person/253_0143.jpg 7 +photo/person/253_0144.jpg 7 +photo/person/253_0145.jpg 7 +photo/person/253_0146.jpg 7 +photo/person/253_0147.jpg 7 +photo/person/253_0148.jpg 7 +photo/person/253_0149.jpg 7 +photo/person/253_0150.jpg 7 +photo/person/253_0151.jpg 7 +photo/person/253_0152.jpg 7 +photo/person/253_0153.jpg 7 +photo/person/253_0154.jpg 7 +photo/person/253_0155.jpg 7 +photo/person/253_0156.jpg 7 +photo/person/253_0157.jpg 7 +photo/person/253_0158.jpg 7 +photo/person/253_0159.jpg 7 +photo/person/253_0160.jpg 7 +photo/person/253_0161.jpg 7 +photo/person/253_0162.jpg 7 +photo/person/253_0163.jpg 7 +photo/person/253_0164.jpg 7 +photo/person/253_0165.jpg 7 +photo/person/253_0166.jpg 7 +photo/person/253_0167.jpg 7 +photo/person/253_0168.jpg 7 +photo/person/253_0169.jpg 7 +photo/person/253_0170.jpg 7 +photo/person/253_0171.jpg 7 +photo/person/253_0172.jpg 7 +photo/person/253_0173.jpg 7 +photo/person/253_0174.jpg 7 +photo/person/253_0175.jpg 7 +photo/person/253_0176.jpg 7 +photo/person/253_0177.jpg 7 +photo/person/253_0178.jpg 7 +photo/person/253_0179.jpg 7 +photo/person/253_0180.jpg 7 +photo/person/253_0181.jpg 7 +photo/person/253_0182.jpg 7 +photo/person/253_0183.jpg 7 +photo/person/253_0184.jpg 7 +photo/person/253_0185.jpg 7 +photo/person/253_0186.jpg 7 +photo/person/253_0187.jpg 7 +photo/person/253_0188.jpg 7 +photo/person/253_0189.jpg 7 +photo/person/253_0190.jpg 7 +photo/person/253_0191.jpg 7 +photo/person/253_0192.jpg 7 +photo/person/253_0193.jpg 7 +photo/person/253_0194.jpg 7 +photo/person/253_0195.jpg 7 +photo/person/253_0196.jpg 7 +photo/person/253_0197.jpg 7 +photo/person/253_0198.jpg 7 +photo/person/253_0199.jpg 7 +photo/person/253_0200.jpg 7 +photo/person/253_0201.jpg 7 +photo/person/253_0202.jpg 7 +photo/person/253_0203.jpg 7 +photo/person/253_0204.jpg 7 +photo/person/253_0205.jpg 7 +photo/person/253_0206.jpg 7 +photo/person/253_0207.jpg 7 +photo/person/253_0208.jpg 7 +photo/person/253_0209.jpg 7 +photo/person/253_0210.jpg 7 +photo/person/253_0211.jpg 7 +photo/person/253_0212.jpg 7 +photo/person/253_0213.jpg 7 +photo/person/253_0214.jpg 7 +photo/person/253_0215.jpg 7 +photo/person/253_0216.jpg 7 +photo/person/253_0217.jpg 7 +photo/person/253_0218.jpg 7 +photo/person/253_0219.jpg 7 +photo/person/253_0220.jpg 7 +photo/person/253_0221.jpg 7 +photo/person/253_0222.jpg 7 +photo/person/253_0223.jpg 7 +photo/person/253_0224.jpg 7 +photo/person/253_0225.jpg 7 +photo/person/253_0226.jpg 7 +photo/person/253_0227.jpg 7 +photo/person/253_0228.jpg 7 +photo/person/253_0229.jpg 7 +photo/person/253_0230.jpg 7 +photo/person/253_0231.jpg 7 +photo/person/253_0232.jpg 7 +photo/person/253_0233.jpg 7 +photo/person/253_0234.jpg 7 +photo/person/253_0235.jpg 7 +photo/person/253_0236.jpg 7 +photo/person/253_0237.jpg 7 +photo/person/253_0238.jpg 7 +photo/person/253_0239.jpg 7 +photo/person/253_0240.jpg 7 +photo/person/253_0241.jpg 7 +photo/person/253_0242.jpg 7 +photo/person/253_0243.jpg 7 +photo/person/253_0244.jpg 7 +photo/person/253_0245.jpg 7 +photo/person/253_0246.jpg 7 +photo/person/253_0247.jpg 7 +photo/person/253_0248.jpg 7 +photo/person/253_0249.jpg 7 +photo/person/253_0250.jpg 7 +photo/person/253_0251.jpg 7 +photo/person/253_0252.jpg 7 +photo/person/253_0253.jpg 7 +photo/person/253_0254.jpg 7 +photo/person/253_0255.jpg 7 +photo/person/253_0256.jpg 7 +photo/person/253_0257.jpg 7 +photo/person/253_0258.jpg 7 +photo/person/253_0259.jpg 7 +photo/person/253_0260.jpg 7 +photo/person/253_0261.jpg 7 +photo/person/253_0262.jpg 7 +photo/person/253_0263.jpg 7 +photo/person/253_0264.jpg 7 +photo/person/253_0265.jpg 7 +photo/person/253_0266.jpg 7 +photo/person/253_0267.jpg 7 +photo/person/253_0268.jpg 7 +photo/person/253_0269.jpg 7 +photo/person/253_0270.jpg 7 +photo/person/253_0271.jpg 7 +photo/person/253_0272.jpg 7 +photo/person/253_0273.jpg 7 +photo/person/253_0274.jpg 7 +photo/person/253_0275.jpg 7 +photo/person/253_0276.jpg 7 +photo/person/253_0277.jpg 7 +photo/person/253_0278.jpg 7 +photo/person/253_0279.jpg 7 +photo/person/253_0280.jpg 7 +photo/person/253_0281.jpg 7 +photo/person/253_0282.jpg 7 +photo/person/253_0283.jpg 7 +photo/person/253_0284.jpg 7 +photo/person/253_0285.jpg 7 +photo/person/253_0286.jpg 7 +photo/person/253_0287.jpg 7 +photo/person/253_0288.jpg 7 +photo/person/253_0289.jpg 7 +photo/person/253_0290.jpg 7 +photo/person/253_0291.jpg 7 +photo/person/253_0292.jpg 7 +photo/person/253_0293.jpg 7 +photo/person/253_0294.jpg 7 +photo/person/253_0295.jpg 7 +photo/person/253_0296.jpg 7 +photo/person/253_0297.jpg 7 +photo/person/253_0298.jpg 7 +photo/person/253_0299.jpg 7 +photo/person/253_0300.jpg 7 +photo/person/253_0301.jpg 7 +photo/person/253_0302.jpg 7 +photo/person/253_0303.jpg 7 +photo/person/253_0304.jpg 7 +photo/person/253_0305.jpg 7 +photo/person/253_0306.jpg 7 +photo/person/253_0307.jpg 7 +photo/person/253_0308.jpg 7 +photo/person/253_0309.jpg 7 +photo/person/253_0310.jpg 7 +photo/person/253_0311.jpg 7 +photo/person/253_0312.jpg 7 +photo/person/253_0313.jpg 7 +photo/person/253_0314.jpg 7 +photo/person/253_0315.jpg 7 +photo/person/253_0316.jpg 7 +photo/person/253_0317.jpg 7 +photo/person/253_0318.jpg 7 +photo/person/253_0319.jpg 7 +photo/person/253_0320.jpg 7 +photo/person/253_0321.jpg 7 +photo/person/253_0322.jpg 7 +photo/person/253_0323.jpg 7 +photo/person/253_0324.jpg 7 +photo/person/253_0325.jpg 7 +photo/person/253_0326.jpg 7 +photo/person/253_0327.jpg 7 +photo/person/253_0328.jpg 7 +photo/person/253_0329.jpg 7 +photo/person/253_0330.jpg 7 +photo/person/253_0331.jpg 7 +photo/person/253_0332.jpg 7 +photo/person/253_0333.jpg 7 +photo/person/253_0334.jpg 7 +photo/person/253_0335.jpg 7 +photo/person/253_0336.jpg 7 +photo/person/253_0337.jpg 7 +photo/person/253_0338.jpg 7 +photo/person/253_0339.jpg 7 +photo/person/253_0340.jpg 7 +photo/person/253_0341.jpg 7 +photo/person/253_0342.jpg 7 +photo/person/253_0343.jpg 7 +photo/person/253_0344.jpg 7 +photo/person/253_0345.jpg 7 +photo/person/253_0346.jpg 7 +photo/person/253_0347.jpg 7 +photo/person/253_0348.jpg 7 +photo/person/253_0349.jpg 7 +photo/person/253_0350.jpg 7 +photo/person/253_0351.jpg 7 +photo/person/253_0352.jpg 7 +photo/person/253_0353.jpg 7 +photo/person/253_0354.jpg 7 +photo/person/253_0355.jpg 7 +photo/person/253_0356.jpg 7 +photo/person/253_0357.jpg 7 +photo/person/253_0358.jpg 7 +photo/person/253_0359.jpg 7 +photo/person/253_0360.jpg 7 +photo/person/253_0361.jpg 7 +photo/person/253_0362.jpg 7 +photo/person/253_0363.jpg 7 +photo/person/253_0364.jpg 7 +photo/person/253_0365.jpg 7 +photo/person/253_0366.jpg 7 +photo/person/253_0367.jpg 7 +photo/person/253_0368.jpg 7 +photo/person/253_0369.jpg 7 +photo/person/253_0370.jpg 7 +photo/person/253_0371.jpg 7 +photo/person/253_0372.jpg 7 +photo/person/253_0373.jpg 7 +photo/person/253_0374.jpg 7 +photo/person/253_0375.jpg 7 +photo/person/253_0376.jpg 7 +photo/person/253_0377.jpg 7 +photo/person/253_0378.jpg 7 +photo/person/253_0379.jpg 7 +photo/person/253_0380.jpg 7 +photo/person/253_0381.jpg 7 +photo/person/253_0382.jpg 7 +photo/person/253_0383.jpg 7 +photo/person/253_0384.jpg 7 +photo/person/253_0385.jpg 7 +photo/person/253_0386.jpg 7 +photo/person/253_0387.jpg 7 +photo/person/253_0388.jpg 7 +photo/person/253_0390.jpg 7 +photo/person/253_0393.jpg 7 +photo/person/253_0394.jpg 7 +photo/person/253_0395.jpg 7 +photo/person/253_0396.jpg 7 +photo/person/253_0397.jpg 7 +photo/person/253_0398.jpg 7 +photo/person/253_0399.jpg 7 +photo/person/253_0400.jpg 7 +photo/person/253_0401.jpg 7 +photo/person/253_0402.jpg 7 +photo/person/253_0403.jpg 7 +photo/person/253_0404.jpg 7 +photo/person/253_0405.jpg 7 +photo/person/253_0406.jpg 7 +photo/person/253_0407.jpg 7 +photo/person/253_0408.jpg 7 +photo/person/253_0409.jpg 7 +photo/person/253_0410.jpg 7 +photo/person/253_0411.jpg 7 +photo/person/253_0412.jpg 7 +photo/person/253_0413.jpg 7 +photo/person/253_0414.jpg 7 +photo/person/253_0415.jpg 7 +photo/person/253_0416.jpg 7 +photo/person/253_0417.jpg 7 +photo/person/253_0418.jpg 7 +photo/person/253_0419.jpg 7 +photo/person/253_0420.jpg 7 +photo/person/253_0421.jpg 7 +photo/person/253_0422.jpg 7 +photo/person/253_0423.jpg 7 +photo/person/253_0424.jpg 7 +photo/person/253_0425.jpg 7 +photo/person/253_0426.jpg 7 +photo/person/253_0427.jpg 7 +photo/person/253_0428.jpg 7 +photo/person/253_0429.jpg 7 +photo/person/253_0430.jpg 7 +photo/person/253_0431.jpg 7 +photo/person/253_0432.jpg 7 +photo/person/253_0433.jpg 7 +photo/person/253_0434.jpg 7 +photo/person/253_0435.jpg 7 diff --git a/domainlab/zdata/pacs_split/photo_train_kfold.txt b/domainlab/zdata/pacs_split/photo_train_kfold.txt new file mode 100644 index 000000000..5edd1d10a --- /dev/null +++ b/domainlab/zdata/pacs_split/photo_train_kfold.txt @@ -0,0 +1,1499 @@ +photo/dog/056_0022.jpg 1 +photo/dog/056_0023.jpg 1 +photo/dog/056_0024.jpg 1 +photo/dog/056_0026.jpg 1 +photo/dog/056_0027.jpg 1 +photo/dog/056_0028.jpg 1 +photo/dog/056_0029.jpg 1 +photo/dog/056_0030.jpg 1 +photo/dog/056_0031.jpg 1 +photo/dog/056_0032.jpg 1 +photo/dog/056_0033.jpg 1 +photo/dog/056_0034.jpg 1 +photo/dog/056_0035.jpg 1 +photo/dog/056_0036.jpg 1 +photo/dog/056_0037.jpg 1 +photo/dog/056_0038.jpg 1 +photo/dog/056_0039.jpg 1 +photo/dog/056_0040.jpg 1 +photo/dog/056_0041.jpg 1 +photo/dog/056_0042.jpg 1 +photo/dog/056_0043.jpg 1 +photo/dog/056_0045.jpg 1 +photo/dog/056_0046.jpg 1 +photo/dog/056_0047.jpg 1 +photo/dog/056_0048.jpg 1 +photo/dog/056_0049.jpg 1 +photo/dog/056_0050.jpg 1 +photo/dog/056_0051.jpg 1 +photo/dog/056_0052.jpg 1 +photo/dog/056_0053.jpg 1 +photo/dog/056_0054.jpg 1 +photo/dog/056_0055.jpg 1 +photo/dog/056_0056.jpg 1 +photo/dog/056_0057.jpg 1 +photo/dog/056_0058.jpg 1 +photo/dog/056_0059.jpg 1 +photo/dog/056_0060.jpg 1 +photo/dog/056_0062.jpg 1 +photo/dog/056_0063.jpg 1 +photo/dog/056_0064.jpg 1 +photo/dog/056_0065.jpg 1 +photo/dog/056_0066.jpg 1 +photo/dog/056_0067.jpg 1 +photo/dog/056_0068.jpg 1 +photo/dog/056_0069.jpg 1 +photo/dog/056_0070.jpg 1 +photo/dog/056_0071.jpg 1 +photo/dog/056_0072.jpg 1 +photo/dog/056_0073.jpg 1 +photo/dog/056_0074.jpg 1 +photo/dog/056_0075.jpg 1 +photo/dog/056_0076.jpg 1 +photo/dog/056_0077.jpg 1 +photo/dog/056_0078.jpg 1 +photo/dog/056_0079.jpg 1 +photo/dog/056_0080.jpg 1 +photo/dog/056_0081.jpg 1 +photo/dog/056_0082.jpg 1 +photo/dog/056_0083.jpg 1 +photo/dog/056_0084.jpg 1 +photo/dog/056_0085.jpg 1 +photo/dog/056_0086.jpg 1 +photo/dog/056_0087.jpg 1 +photo/dog/056_0088.jpg 1 +photo/dog/056_0089.jpg 1 +photo/dog/056_0090.jpg 1 +photo/dog/056_0091.jpg 1 +photo/dog/056_0092.jpg 1 +photo/dog/056_0093.jpg 1 +photo/dog/056_0095.jpg 1 +photo/dog/056_0097.jpg 1 +photo/dog/056_0098.jpg 1 +photo/dog/056_0099.jpg 1 +photo/dog/056_0101.jpg 1 +photo/dog/056_0102.jpg 1 +photo/dog/n02103406_343.jpg 1 +photo/dog/n02103406_346.jpg 1 +photo/dog/n02103406_371.jpg 1 +photo/dog/n02103406_865.jpg 1 +photo/dog/n02103406_936.jpg 1 +photo/dog/n02103406_995.jpg 1 +photo/dog/n02103406_1011.jpg 1 +photo/dog/n02103406_1138.jpg 1 +photo/dog/n02103406_1170.jpg 1 +photo/dog/n02103406_1247.jpg 1 +photo/dog/n02103406_1599.jpg 1 +photo/dog/n02103406_1754.jpg 1 +photo/dog/n02103406_2209.jpg 1 +photo/dog/n02103406_2706.jpg 1 +photo/dog/n02103406_2954.jpg 1 +photo/dog/n02103406_3056.jpg 1 +photo/dog/n02103406_3108.jpg 1 +photo/dog/n02103406_3132.jpg 1 +photo/dog/n02103406_3255.jpg 1 +photo/dog/n02103406_3299.jpg 1 +photo/dog/n02103406_3326.jpg 1 +photo/dog/n02103406_3401.jpg 1 +photo/dog/n02103406_3538.jpg 1 +photo/dog/n02103406_3743.jpg 1 +photo/dog/n02103406_3750.jpg 1 +photo/dog/n02103406_3964.jpg 1 +photo/dog/n02103406_4068.jpg 1 +photo/dog/n02103406_4849.jpg 1 +photo/dog/n02103406_4916.jpg 1 +photo/dog/n02103406_5035.jpg 1 +photo/dog/n02103406_5216.jpg 1 +photo/dog/n02103406_5224.jpg 1 +photo/dog/n02103406_5456.jpg 1 +photo/dog/n02103406_5505.jpg 1 +photo/dog/n02103406_5563.jpg 1 +photo/dog/n02103406_5601.jpg 1 +photo/dog/n02103406_6274.jpg 1 +photo/dog/n02103406_6461.jpg 1 +photo/dog/n02103406_6530.jpg 1 +photo/dog/n02103406_6857.jpg 1 +photo/dog/n02103406_7201.jpg 1 +photo/dog/n02103406_7368.jpg 1 +photo/dog/n02103406_7521.jpg 1 +photo/dog/n02103406_7708.jpg 1 +photo/dog/n02103406_8004.jpg 1 +photo/dog/n02103406_8280.jpg 1 +photo/dog/n02103406_8362.jpg 1 +photo/dog/n02103406_8421.jpg 1 +photo/dog/n02103406_13049.jpg 1 +photo/dog/n02106662_466.jpg 1 +photo/dog/n02106662_928.jpg 1 +photo/dog/n02106662_1874.jpg 1 +photo/dog/n02106662_1922.jpg 1 +photo/dog/n02106662_2101.jpg 1 +photo/dog/n02106662_2157.jpg 1 +photo/dog/n02106662_2377.jpg 1 +photo/dog/n02106662_2740.jpg 1 +photo/dog/n02106662_5001.jpg 1 +photo/dog/n02106662_7885.jpg 1 +photo/dog/n02106662_7960.jpg 1 +photo/dog/n02106662_8511.jpg 1 +photo/dog/n02106662_8870.jpg 1 +photo/dog/n02106662_10406.jpg 1 +photo/dog/n02106662_11133.jpg 1 +photo/dog/n02106662_13178.jpg 1 +photo/dog/n02106662_13912.jpg 1 +photo/dog/n02106662_15858.jpg 1 +photo/dog/n02106662_18402.jpg 1 +photo/dog/n02106662_18405.jpg 1 +photo/dog/n02106662_18922.jpg 1 +photo/dog/n02106662_18953.jpg 1 +photo/dog/n02106662_24019.jpg 1 +photo/dog/n02106662_24577.jpg 1 +photo/dog/n02106662_24786.jpg 1 +photo/dog/n02106662_25917.jpg 1 +photo/dog/n02106662_26549.jpg 1 +photo/dog/n02106662_27393.jpg 1 +photo/dog/n02109525_704.jpg 1 +photo/dog/n02109525_1893.jpg 1 +photo/dog/n02109525_3202.jpg 1 +photo/dog/n02109525_3782.jpg 1 +photo/dog/n02109525_5013.jpg 1 +photo/dog/n02109525_5583.jpg 1 +photo/dog/n02109525_5966.jpg 1 +photo/dog/n02109525_6693.jpg 1 +photo/dog/n02109525_7874.jpg 1 +photo/dog/n02109525_8211.jpg 1 +photo/dog/n02109525_8457.jpg 1 +photo/dog/n02109525_9037.jpg 1 +photo/dog/n02109525_10297.jpg 1 +photo/dog/n02109525_11444.jpg 1 +photo/dog/n02109525_12875.jpg 1 +photo/dog/n02109525_13700.jpg 1 +photo/dog/n02109525_16346.jpg 1 +photo/dog/n02109525_18347.jpg 1 +photo/elephant/064_0022.jpg 2 +photo/elephant/064_0023.jpg 2 +photo/elephant/064_0024.jpg 2 +photo/elephant/064_0025.jpg 2 +photo/elephant/064_0030.jpg 2 +photo/elephant/064_0031.jpg 2 +photo/elephant/064_0032.jpg 2 +photo/elephant/064_0033.jpg 2 +photo/elephant/064_0034.jpg 2 +photo/elephant/064_0035.jpg 2 +photo/elephant/064_0036.jpg 2 +photo/elephant/064_0037.jpg 2 +photo/elephant/064_0038.jpg 2 +photo/elephant/064_0039.jpg 2 +photo/elephant/064_0040.jpg 2 +photo/elephant/064_0041.jpg 2 +photo/elephant/064_0042.jpg 2 +photo/elephant/064_0043.jpg 2 +photo/elephant/064_0044.jpg 2 +photo/elephant/064_0045.jpg 2 +photo/elephant/064_0047.jpg 2 +photo/elephant/064_0048.jpg 2 +photo/elephant/064_0049.jpg 2 +photo/elephant/064_0051.jpg 2 +photo/elephant/064_0052.jpg 2 +photo/elephant/064_0053.jpg 2 +photo/elephant/064_0054.jpg 2 +photo/elephant/064_0055.jpg 2 +photo/elephant/064_0056.jpg 2 +photo/elephant/064_0057.jpg 2 +photo/elephant/064_0058.jpg 2 +photo/elephant/064_0059.jpg 2 +photo/elephant/064_0060.jpg 2 +photo/elephant/064_0061.jpg 2 +photo/elephant/064_0062.jpg 2 +photo/elephant/064_0063.jpg 2 +photo/elephant/064_0064.jpg 2 +photo/elephant/064_0065.jpg 2 +photo/elephant/064_0066.jpg 2 +photo/elephant/064_0067.jpg 2 +photo/elephant/064_0068.jpg 2 +photo/elephant/064_0070.jpg 2 +photo/elephant/064_0071.jpg 2 +photo/elephant/064_0072.jpg 2 +photo/elephant/064_0073.jpg 2 +photo/elephant/064_0074.jpg 2 +photo/elephant/064_0075.jpg 2 +photo/elephant/064_0076.jpg 2 +photo/elephant/064_0077.jpg 2 +photo/elephant/064_0078.jpg 2 +photo/elephant/064_0079.jpg 2 +photo/elephant/064_0080.jpg 2 +photo/elephant/064_0081.jpg 2 +photo/elephant/064_0084.jpg 2 +photo/elephant/064_0085.jpg 2 +photo/elephant/064_0086.jpg 2 +photo/elephant/064_0087.jpg 2 +photo/elephant/064_0088.jpg 2 +photo/elephant/064_0089.jpg 2 +photo/elephant/064_0090.jpg 2 +photo/elephant/064_0092.jpg 2 +photo/elephant/064_0093.jpg 2 +photo/elephant/064_0094.jpg 2 +photo/elephant/064_0095.jpg 2 +photo/elephant/064_0096.jpg 2 +photo/elephant/064_0097.jpg 2 +photo/elephant/064_0098.jpg 2 +photo/elephant/064_0099.jpg 2 +photo/elephant/064_0100.jpg 2 +photo/elephant/064_0101.jpg 2 +photo/elephant/064_0102.jpg 2 +photo/elephant/064_0105.jpg 2 +photo/elephant/064_0106.jpg 2 +photo/elephant/064_0107.jpg 2 +photo/elephant/064_0108.jpg 2 +photo/elephant/064_0109.jpg 2 +photo/elephant/064_0110.jpg 2 +photo/elephant/064_0111.jpg 2 +photo/elephant/064_0112.jpg 2 +photo/elephant/064_0113.jpg 2 +photo/elephant/064_0114.jpg 2 +photo/elephant/064_0115.jpg 2 +photo/elephant/064_0116.jpg 2 +photo/elephant/064_0117.jpg 2 +photo/elephant/064_0118.jpg 2 +photo/elephant/064_0119.jpg 2 +photo/elephant/064_0120.jpg 2 +photo/elephant/064_0121.jpg 2 +photo/elephant/064_0122.jpg 2 +photo/elephant/064_0123.jpg 2 +photo/elephant/064_0124.jpg 2 +photo/elephant/064_0125.jpg 2 +photo/elephant/064_0126.jpg 2 +photo/elephant/064_0127.jpg 2 +photo/elephant/064_0129.jpg 2 +photo/elephant/064_0130.jpg 2 +photo/elephant/064_0131.jpg 2 +photo/elephant/n02503517_79.jpg 2 +photo/elephant/n02503517_86.jpg 2 +photo/elephant/n02503517_184.jpg 2 +photo/elephant/n02503517_194.jpg 2 +photo/elephant/n02503517_564.jpg 2 +photo/elephant/n02503517_753.jpg 2 +photo/elephant/n02503517_759.jpg 2 +photo/elephant/n02503517_792.jpg 2 +photo/elephant/n02503517_1292.jpg 2 +photo/elephant/n02503517_1359.jpg 2 +photo/elephant/n02503517_1383.jpg 2 +photo/elephant/n02503517_1415.jpg 2 +photo/elephant/n02503517_1453.jpg 2 +photo/elephant/n02503517_1583.jpg 2 +photo/elephant/n02503517_1829.jpg 2 +photo/elephant/n02503517_2061.jpg 2 +photo/elephant/n02503517_2444.jpg 2 +photo/elephant/n02503517_2547.jpg 2 +photo/elephant/n02503517_2802.jpg 2 +photo/elephant/n02503517_2804.jpg 2 +photo/elephant/n02503517_2925.jpg 2 +photo/elephant/n02503517_2993.jpg 2 +photo/elephant/n02503517_3037.jpg 2 +photo/elephant/n02503517_3072.jpg 2 +photo/elephant/n02503517_3108.jpg 2 +photo/elephant/n02503517_3799.jpg 2 +photo/elephant/n02503517_3803.jpg 2 +photo/elephant/n02503517_3808.jpg 2 +photo/elephant/n02503517_3879.jpg 2 +photo/elephant/n02503517_4221.jpg 2 +photo/elephant/n02503517_4247.jpg 2 +photo/elephant/n02503517_4253.jpg 2 +photo/elephant/n02503517_4413.jpg 2 +photo/elephant/n02503517_4605.jpg 2 +photo/elephant/n02503517_5117.jpg 2 +photo/elephant/n02503517_5287.jpg 2 +photo/elephant/n02503517_5418.jpg 2 +photo/elephant/n02503517_5420.jpg 2 +photo/elephant/n02503517_5527.jpg 2 +photo/elephant/n02503517_5892.jpg 2 +photo/elephant/n02503517_5909.jpg 2 +photo/elephant/n02503517_6032.jpg 2 +photo/elephant/n02503517_6232.jpg 2 +photo/elephant/n02503517_6396.jpg 2 +photo/elephant/n02503517_6479.jpg 2 +photo/elephant/n02503517_6611.jpg 2 +photo/elephant/n02503517_6624.jpg 2 +photo/elephant/n02503517_6661.jpg 2 +photo/elephant/n02503517_6784.jpg 2 +photo/elephant/n02503517_6880.jpg 2 +photo/elephant/n02503517_7020.jpg 2 +photo/elephant/n02503517_7031.jpg 2 +photo/elephant/n02503517_7083.jpg 2 +photo/elephant/n02503517_7173.jpg 2 +photo/elephant/n02503517_7211.jpg 2 +photo/elephant/n02503517_7393.jpg 2 +photo/elephant/n02503517_8137.jpg 2 +photo/elephant/n02503517_8205.jpg 2 +photo/elephant/n02503517_8222.jpg 2 +photo/elephant/n02503517_8265.jpg 2 +photo/elephant/n02503517_8292.jpg 2 +photo/elephant/n02503517_8518.jpg 2 +photo/elephant/n02503517_8571.jpg 2 +photo/elephant/n02503517_8757.jpg 2 +photo/elephant/n02503517_8901.jpg 2 +photo/elephant/n02503517_8904.jpg 2 +photo/elephant/n02503517_8938.jpg 2 +photo/elephant/n02503517_9043.jpg 2 +photo/elephant/n02503517_9154.jpg 2 +photo/elephant/n02503517_9241.jpg 2 +photo/elephant/n02503517_9270.jpg 2 +photo/elephant/n02503517_9827.jpg 2 +photo/elephant/n02503517_10036.jpg 2 +photo/elephant/n02503517_10075.jpg 2 +photo/elephant/n02503517_10193.jpg 2 +photo/elephant/n02503517_10275.jpg 2 +photo/elephant/n02503517_10300.jpg 2 +photo/elephant/n02503517_10439.jpg 2 +photo/elephant/n02503517_10440.jpg 2 +photo/elephant/n02503517_10528.jpg 2 +photo/elephant/n02503517_10558.jpg 2 +photo/elephant/n02503517_10778.jpg 2 +photo/elephant/n02503517_11873.jpg 2 +photo/elephant/n02503517_12688.jpg 2 +photo/giraffe/084_0020.jpg 3 +photo/giraffe/084_0021.jpg 3 +photo/giraffe/084_0022.jpg 3 +photo/giraffe/084_0023.jpg 3 +photo/giraffe/084_0024.jpg 3 +photo/giraffe/084_0025.jpg 3 +photo/giraffe/084_0026.jpg 3 +photo/giraffe/084_0027.jpg 3 +photo/giraffe/084_0028.jpg 3 +photo/giraffe/084_0029.jpg 3 +photo/giraffe/084_0030.jpg 3 +photo/giraffe/084_0031.jpg 3 +photo/giraffe/084_0032.jpg 3 +photo/giraffe/084_0033.jpg 3 +photo/giraffe/084_0034.jpg 3 +photo/giraffe/084_0035.jpg 3 +photo/giraffe/084_0036.jpg 3 +photo/giraffe/084_0038.jpg 3 +photo/giraffe/084_0039.jpg 3 +photo/giraffe/084_0040.jpg 3 +photo/giraffe/084_0041.jpg 3 +photo/giraffe/084_0042.jpg 3 +photo/giraffe/084_0043.jpg 3 +photo/giraffe/084_0044.jpg 3 +photo/giraffe/084_0045.jpg 3 +photo/giraffe/084_0046.jpg 3 +photo/giraffe/084_0047.jpg 3 +photo/giraffe/084_0048.jpg 3 +photo/giraffe/084_0049.jpg 3 +photo/giraffe/084_0050.jpg 3 +photo/giraffe/084_0051.jpg 3 +photo/giraffe/084_0052.jpg 3 +photo/giraffe/084_0053.jpg 3 +photo/giraffe/084_0054.jpg 3 +photo/giraffe/084_0055.jpg 3 +photo/giraffe/084_0056.jpg 3 +photo/giraffe/084_0057.jpg 3 +photo/giraffe/084_0058.jpg 3 +photo/giraffe/084_0059.jpg 3 +photo/giraffe/084_0060.jpg 3 +photo/giraffe/084_0061.jpg 3 +photo/giraffe/084_0062.jpg 3 +photo/giraffe/084_0063.jpg 3 +photo/giraffe/084_0064.jpg 3 +photo/giraffe/084_0065.jpg 3 +photo/giraffe/084_0066.jpg 3 +photo/giraffe/084_0067.jpg 3 +photo/giraffe/084_0068.jpg 3 +photo/giraffe/084_0069.jpg 3 +photo/giraffe/084_0070.jpg 3 +photo/giraffe/084_0071.jpg 3 +photo/giraffe/084_0072.jpg 3 +photo/giraffe/084_0073.jpg 3 +photo/giraffe/084_0074.jpg 3 +photo/giraffe/084_0075.jpg 3 +photo/giraffe/084_0076.jpg 3 +photo/giraffe/084_0077.jpg 3 +photo/giraffe/084_0078.jpg 3 +photo/giraffe/084_0079.jpg 3 +photo/giraffe/084_0080.jpg 3 +photo/giraffe/084_0081.jpg 3 +photo/giraffe/084_0082.jpg 3 +photo/giraffe/084_0083.jpg 3 +photo/giraffe/084_0084.jpg 3 +photo/giraffe/n02439033_67.jpg 3 +photo/giraffe/n02439033_221.jpg 3 +photo/giraffe/n02439033_376.jpg 3 +photo/giraffe/n02439033_569.jpg 3 +photo/giraffe/n02439033_628.jpg 3 +photo/giraffe/n02439033_866.jpg 3 +photo/giraffe/n02439033_991.jpg 3 +photo/giraffe/n02439033_1327.jpg 3 +photo/giraffe/n02439033_1508.jpg 3 +photo/giraffe/n02439033_2486.jpg 3 +photo/giraffe/n02439033_2500.jpg 3 +photo/giraffe/n02439033_2677.jpg 3 +photo/giraffe/n02439033_3944.jpg 3 +photo/giraffe/n02439033_4601.jpg 3 +photo/giraffe/n02439033_5004.jpg 3 +photo/giraffe/n02439033_5652.jpg 3 +photo/giraffe/n02439033_6552.jpg 3 +photo/giraffe/n02439033_8789.jpg 3 +photo/giraffe/n02439033_8846.jpg 3 +photo/giraffe/n02439033_8875.jpg 3 +photo/giraffe/n02439033_9257.jpg 3 +photo/giraffe/n02439033_9261.jpg 3 +photo/giraffe/n02439033_9398.jpg 3 +photo/giraffe/n02439033_9472.jpg 3 +photo/giraffe/n02439033_9598.jpg 3 +photo/giraffe/n02439033_9604.jpg 3 +photo/giraffe/n02439033_9679.jpg 3 +photo/giraffe/n02439033_9719.jpg 3 +photo/giraffe/n02439033_10130.jpg 3 +photo/giraffe/n02439033_10164.jpg 3 +photo/giraffe/n02439033_10279.jpg 3 +photo/giraffe/n02439033_10295.jpg 3 +photo/giraffe/n02439033_10453.jpg 3 +photo/giraffe/n02439033_10491.jpg 3 +photo/giraffe/n02439033_10541.jpg 3 +photo/giraffe/n02439033_10616.jpg 3 +photo/giraffe/n02439033_10802.jpg 3 +photo/giraffe/n02439033_10803.jpg 3 +photo/giraffe/n02439033_10811.jpg 3 +photo/giraffe/n02439033_10839.jpg 3 +photo/giraffe/n02439033_10919.jpg 3 +photo/giraffe/n02439033_11059.jpg 3 +photo/giraffe/n02439033_11114.jpg 3 +photo/giraffe/n02439033_11130.jpg 3 +photo/giraffe/n02439033_11215.jpg 3 +photo/giraffe/n02439033_11273.jpg 3 +photo/giraffe/n02439033_11328.jpg 3 +photo/giraffe/n02439033_11458.jpg 3 +photo/giraffe/n02439033_11486.jpg 3 +photo/giraffe/n02439033_11487.jpg 3 +photo/giraffe/n02439033_11504.jpg 3 +photo/giraffe/n02439033_11599.jpg 3 +photo/giraffe/n02439033_11627.jpg 3 +photo/giraffe/n02439033_11666.jpg 3 +photo/giraffe/n02439033_11683.jpg 3 +photo/giraffe/n02439033_11715.jpg 3 +photo/giraffe/n02439033_11845.jpg 3 +photo/giraffe/n02439033_11894.jpg 3 +photo/giraffe/n02439033_12059.jpg 3 +photo/giraffe/n02439033_12413.jpg 3 +photo/giraffe/n02439033_12485.jpg 3 +photo/giraffe/n02439033_12680.jpg 3 +photo/giraffe/n02439033_12930.jpg 3 +photo/giraffe/n02439033_12939.jpg 3 +photo/giraffe/n02439033_12987.jpg 3 +photo/giraffe/n02439033_13236.jpg 3 +photo/giraffe/n02439033_13384.jpg 3 +photo/giraffe/n02439033_13430.jpg 3 +photo/giraffe/n02439033_13602.jpg 3 +photo/giraffe/n02439033_13868.jpg 3 +photo/giraffe/n02439033_14040.jpg 3 +photo/giraffe/n02439033_14060.jpg 3 +photo/giraffe/n02439033_14121.jpg 3 +photo/giraffe/n02439033_14148.jpg 3 +photo/giraffe/n02439033_14184.jpg 3 +photo/giraffe/n02439033_14322.jpg 3 +photo/giraffe/n02439033_14497.jpg 3 +photo/giraffe/n02439033_14554.jpg 3 +photo/giraffe/n02439033_14580.jpg 3 +photo/giraffe/n02439033_14600.jpg 3 +photo/giraffe/n02439033_14609.jpg 3 +photo/giraffe/n02439033_14724.jpg 3 +photo/giraffe/n02439033_14764.jpg 3 +photo/giraffe/n02439033_14781.jpg 3 +photo/giraffe/n02439033_14784.jpg 3 +photo/giraffe/n02439033_14846.jpg 3 +photo/giraffe/n02439033_14872.jpg 3 +photo/giraffe/n02439033_14962.jpg 3 +photo/giraffe/n02439033_15005.jpg 3 +photo/giraffe/n02439033_15384.jpg 3 +photo/giraffe/n02439033_15401.jpg 3 +photo/giraffe/n02439033_15453.jpg 3 +photo/giraffe/n02439033_15479.jpg 3 +photo/giraffe/n02439033_15540.jpg 3 +photo/giraffe/n02439033_15555.jpg 3 +photo/giraffe/n02439033_15936.jpg 3 +photo/giraffe/n02439033_16085.jpg 3 +photo/giraffe/n02439033_16356.jpg 3 +photo/giraffe/n02439033_16483.jpg 3 +photo/guitar/063_0024.jpg 4 +photo/guitar/063_0025.jpg 4 +photo/guitar/063_0026.jpg 4 +photo/guitar/063_0027.jpg 4 +photo/guitar/063_0028.jpg 4 +photo/guitar/063_0029.jpg 4 +photo/guitar/063_0030.jpg 4 +photo/guitar/063_0031.jpg 4 +photo/guitar/063_0032.jpg 4 +photo/guitar/063_0035.jpg 4 +photo/guitar/063_0036.jpg 4 +photo/guitar/063_0037.jpg 4 +photo/guitar/063_0038.jpg 4 +photo/guitar/063_0039.jpg 4 +photo/guitar/063_0040.jpg 4 +photo/guitar/063_0041.jpg 4 +photo/guitar/063_0042.jpg 4 +photo/guitar/063_0043.jpg 4 +photo/guitar/063_0045.jpg 4 +photo/guitar/063_0046.jpg 4 +photo/guitar/063_0047.jpg 4 +photo/guitar/063_0048.jpg 4 +photo/guitar/063_0049.jpg 4 +photo/guitar/063_0050.jpg 4 +photo/guitar/063_0051.jpg 4 +photo/guitar/063_0052.jpg 4 +photo/guitar/063_0053.jpg 4 +photo/guitar/063_0054.jpg 4 +photo/guitar/063_0055.jpg 4 +photo/guitar/063_0056.jpg 4 +photo/guitar/063_0059.jpg 4 +photo/guitar/063_0061.jpg 4 +photo/guitar/063_0062.jpg 4 +photo/guitar/063_0065.jpg 4 +photo/guitar/063_0067.jpg 4 +photo/guitar/063_0068.jpg 4 +photo/guitar/063_0069.jpg 4 +photo/guitar/063_0071.jpg 4 +photo/guitar/063_0072.jpg 4 +photo/guitar/063_0073.jpg 4 +photo/guitar/063_0074.jpg 4 +photo/guitar/063_0075.jpg 4 +photo/guitar/063_0076.jpg 4 +photo/guitar/063_0077.jpg 4 +photo/guitar/063_0078.jpg 4 +photo/guitar/063_0079.jpg 4 +photo/guitar/063_0080.jpg 4 +photo/guitar/063_0081.jpg 4 +photo/guitar/063_0082.jpg 4 +photo/guitar/063_0084.jpg 4 +photo/guitar/063_0085.jpg 4 +photo/guitar/063_0086.jpg 4 +photo/guitar/063_0087.jpg 4 +photo/guitar/063_0088.jpg 4 +photo/guitar/063_0089.jpg 4 +photo/guitar/063_0090.jpg 4 +photo/guitar/063_0091.jpg 4 +photo/guitar/063_0092.jpg 4 +photo/guitar/063_0093.jpg 4 +photo/guitar/063_0094.jpg 4 +photo/guitar/063_0095.jpg 4 +photo/guitar/063_0096.jpg 4 +photo/guitar/063_0097.jpg 4 +photo/guitar/063_0098.jpg 4 +photo/guitar/063_0099.jpg 4 +photo/guitar/063_0100.jpg 4 +photo/guitar/063_0101.jpg 4 +photo/guitar/063_0102.jpg 4 +photo/guitar/063_0103.jpg 4 +photo/guitar/063_0104.jpg 4 +photo/guitar/063_0105.jpg 4 +photo/guitar/063_0106.jpg 4 +photo/guitar/063_0107.jpg 4 +photo/guitar/063_0108.jpg 4 +photo/guitar/063_0109.jpg 4 +photo/guitar/063_0110.jpg 4 +photo/guitar/063_0111.jpg 4 +photo/guitar/063_0112.jpg 4 +photo/guitar/063_0113.jpg 4 +photo/guitar/063_0114.jpg 4 +photo/guitar/063_0115.jpg 4 +photo/guitar/063_0116.jpg 4 +photo/guitar/063_0117.jpg 4 +photo/guitar/063_0118.jpg 4 +photo/guitar/063_0119.jpg 4 +photo/guitar/063_0120.jpg 4 +photo/guitar/063_0121.jpg 4 +photo/guitar/063_0122.jpg 4 +photo/guitar/n02676566_307.jpg 4 +photo/guitar/n02676566_330.jpg 4 +photo/guitar/n02676566_659.jpg 4 +photo/guitar/n02676566_1324.jpg 4 +photo/guitar/n02676566_2380.jpg 4 +photo/guitar/n02676566_3360.jpg 4 +photo/guitar/n02676566_4058.jpg 4 +photo/guitar/n02676566_4189.jpg 4 +photo/guitar/n02676566_4469.jpg 4 +photo/guitar/n02676566_4605.jpg 4 +photo/guitar/n02676566_4699.jpg 4 +photo/guitar/n02676566_5489.jpg 4 +photo/guitar/n02676566_5735.jpg 4 +photo/guitar/n02676566_6150.jpg 4 +photo/guitar/n02676566_6402.jpg 4 +photo/guitar/n02676566_6430.jpg 4 +photo/guitar/n02676566_6560.jpg 4 +photo/guitar/n02676566_6631.jpg 4 +photo/guitar/n02676566_6704.jpg 4 +photo/guitar/n02676566_6914.jpg 4 +photo/guitar/n02676566_6948.jpg 4 +photo/guitar/n02676566_7385.jpg 4 +photo/guitar/n02676566_7770.jpg 4 +photo/guitar/n02676566_7830.jpg 4 +photo/guitar/n02676566_7844.jpg 4 +photo/guitar/n02676566_7927.jpg 4 +photo/guitar/n02676566_8268.jpg 4 +photo/guitar/n02676566_8309.jpg 4 +photo/guitar/n02676566_8467.jpg 4 +photo/guitar/n02676566_8618.jpg 4 +photo/guitar/n02676566_8820.jpg 4 +photo/guitar/n02676566_8859.jpg 4 +photo/guitar/n02676566_8997.jpg 4 +photo/guitar/n02676566_9062.jpg 4 +photo/guitar/n02676566_9243.jpg 4 +photo/guitar/n02676566_9254.jpg 4 +photo/guitar/n02676566_9451.jpg 4 +photo/guitar/n02676566_9577.jpg 4 +photo/guitar/n02676566_9661.jpg 4 +photo/guitar/n02676566_9936.jpg 4 +photo/guitar/n02676566_11573.jpg 4 +photo/guitar/n02676566_12344.jpg 4 +photo/guitar/n03272010_392.jpg 4 +photo/guitar/n03272010_446.jpg 4 +photo/guitar/n03272010_1708.jpg 4 +photo/guitar/n03272010_3732.jpg 4 +photo/guitar/n03272010_5483.jpg 4 +photo/guitar/n03272010_5887.jpg 4 +photo/guitar/n03272010_6255.jpg 4 +photo/guitar/n03272010_6291.jpg 4 +photo/guitar/n03272010_6662.jpg 4 +photo/guitar/n03272010_6727.jpg 4 +photo/guitar/n03272010_6737.jpg 4 +photo/guitar/n03272010_6799.jpg 4 +photo/guitar/n03272010_6809.jpg 4 +photo/guitar/n03272010_6820.jpg 4 +photo/guitar/n03272010_6926.jpg 4 +photo/guitar/n03272010_7092.jpg 4 +photo/guitar/n03272010_7390.jpg 4 +photo/guitar/n03272010_7729.jpg 4 +photo/guitar/n03272010_9557.jpg 4 +photo/guitar/n03272010_9858.jpg 4 +photo/guitar/n03272010_9899.jpg 4 +photo/guitar/n03272010_10441.jpg 4 +photo/guitar/n03272010_10795.jpg 4 +photo/guitar/n03272010_12151.jpg 4 +photo/guitar/n03272010_12468.jpg 4 +photo/guitar/n03467517_6423.jpg 4 +photo/guitar/n03467517_7007.jpg 4 +photo/guitar/n03467517_8929.jpg 4 +photo/guitar/n03467517_11020.jpg 4 +photo/guitar/n03467517_12925.jpg 4 +photo/guitar/n03467517_17233.jpg 4 +photo/guitar/n03467517_19701.jpg 4 +photo/guitar/n03467517_21884.jpg 4 +photo/guitar/n03467517_22246.jpg 4 +photo/guitar/n03467517_22785.jpg 4 +photo/guitar/n03467517_23229.jpg 4 +photo/guitar/n03467517_24525.jpg 4 +photo/horse/105_0018.jpg 5 +photo/horse/105_0050.jpg 5 +photo/horse/105_0053.jpg 5 +photo/horse/105_0056.jpg 5 +photo/horse/105_0058.jpg 5 +photo/horse/105_0059.jpg 5 +photo/horse/105_0063.jpg 5 +photo/horse/105_0066.jpg 5 +photo/horse/105_0067.jpg 5 +photo/horse/105_0070.jpg 5 +photo/horse/105_0071.jpg 5 +photo/horse/105_0072.jpg 5 +photo/horse/105_0073.jpg 5 +photo/horse/105_0074.jpg 5 +photo/horse/105_0075.jpg 5 +photo/horse/105_0076.jpg 5 +photo/horse/105_0077.jpg 5 +photo/horse/105_0081.jpg 5 +photo/horse/105_0083.jpg 5 +photo/horse/105_0084.jpg 5 +photo/horse/105_0086.jpg 5 +photo/horse/105_0088.jpg 5 +photo/horse/105_0089.jpg 5 +photo/horse/105_0090.jpg 5 +photo/horse/105_0091.jpg 5 +photo/horse/105_0092.jpg 5 +photo/horse/105_0099.jpg 5 +photo/horse/105_0101.jpg 5 +photo/horse/105_0103.jpg 5 +photo/horse/105_0104.jpg 5 +photo/horse/105_0105.jpg 5 +photo/horse/105_0106.jpg 5 +photo/horse/105_0108.jpg 5 +photo/horse/105_0109.jpg 5 +photo/horse/105_0111.jpg 5 +photo/horse/105_0115.jpg 5 +photo/horse/105_0116.jpg 5 +photo/horse/105_0118.jpg 5 +photo/horse/105_0120.jpg 5 +photo/horse/105_0121.jpg 5 +photo/horse/105_0123.jpg 5 +photo/horse/105_0124.jpg 5 +photo/horse/105_0125.jpg 5 +photo/horse/105_0130.jpg 5 +photo/horse/105_0131.jpg 5 +photo/horse/105_0134.jpg 5 +photo/horse/105_0135.jpg 5 +photo/horse/105_0137.jpg 5 +photo/horse/105_0138.jpg 5 +photo/horse/105_0139.jpg 5 +photo/horse/105_0140.jpg 5 +photo/horse/105_0143.jpg 5 +photo/horse/105_0146.jpg 5 +photo/horse/105_0147.jpg 5 +photo/horse/105_0149.jpg 5 +photo/horse/105_0150.jpg 5 +photo/horse/105_0154.jpg 5 +photo/horse/105_0156.jpg 5 +photo/horse/105_0157.jpg 5 +photo/horse/105_0161.jpg 5 +photo/horse/105_0164.jpg 5 +photo/horse/105_0165.jpg 5 +photo/horse/105_0172.jpg 5 +photo/horse/105_0173.jpg 5 +photo/horse/105_0174.jpg 5 +photo/horse/105_0175.jpg 5 +photo/horse/105_0176.jpg 5 +photo/horse/105_0177.jpg 5 +photo/horse/105_0180.jpg 5 +photo/horse/105_0181.jpg 5 +photo/horse/105_0182.jpg 5 +photo/horse/105_0183.jpg 5 +photo/horse/105_0184.jpg 5 +photo/horse/105_0185.jpg 5 +photo/horse/105_0193.jpg 5 +photo/horse/105_0194.jpg 5 +photo/horse/105_0196.jpg 5 +photo/horse/105_0199.jpg 5 +photo/horse/105_0203.jpg 5 +photo/horse/105_0205.jpg 5 +photo/horse/105_0206.jpg 5 +photo/horse/105_0207.jpg 5 +photo/horse/105_0208.jpg 5 +photo/horse/105_0210.jpg 5 +photo/horse/105_0215.jpg 5 +photo/horse/105_0223.jpg 5 +photo/horse/105_0229.jpg 5 +photo/horse/105_0230.jpg 5 +photo/horse/105_0232.jpg 5 +photo/horse/105_0236.jpg 5 +photo/horse/105_0240.jpg 5 +photo/horse/105_0241.jpg 5 +photo/horse/105_0249.jpg 5 +photo/horse/105_0253.jpg 5 +photo/horse/105_0255.jpg 5 +photo/horse/105_0257.jpg 5 +photo/horse/105_0260.jpg 5 +photo/horse/105_0264.jpg 5 +photo/horse/105_0265.jpg 5 +photo/horse/105_0266.jpg 5 +photo/horse/105_0269.jpg 5 +photo/horse/105_0270.jpg 5 +photo/horse/n02374451_54.jpg 5 +photo/horse/n02374451_245.jpg 5 +photo/horse/n02374451_257.jpg 5 +photo/horse/n02374451_262.jpg 5 +photo/horse/n02374451_388.jpg 5 +photo/horse/n02374451_468.jpg 5 +photo/horse/n02374451_490.jpg 5 +photo/horse/n02374451_503.jpg 5 +photo/horse/n02374451_597.jpg 5 +photo/horse/n02374451_777.jpg 5 +photo/horse/n02374451_779.jpg 5 +photo/horse/n02374451_916.jpg 5 +photo/horse/n02374451_925.jpg 5 +photo/horse/n02374451_929.jpg 5 +photo/horse/n02374451_1189.jpg 5 +photo/horse/n02374451_1234.jpg 5 +photo/horse/n02374451_1443.jpg 5 +photo/horse/n02374451_2248.jpg 5 +photo/horse/n02374451_2372.jpg 5 +photo/horse/n02374451_2478.jpg 5 +photo/horse/n02374451_2616.jpg 5 +photo/horse/n02374451_2733.jpg 5 +photo/horse/n02374451_2743.jpg 5 +photo/horse/n02374451_2825.jpg 5 +photo/horse/n02374451_3388.jpg 5 +photo/horse/n02374451_4538.jpg 5 +photo/horse/n02374451_4553.jpg 5 +photo/horse/n02374451_4795.jpg 5 +photo/horse/n02374451_4818.jpg 5 +photo/horse/n02374451_4963.jpg 5 +photo/horse/n02374451_6192.jpg 5 +photo/horse/n02374451_7631.jpg 5 +photo/horse/n02374451_8065.jpg 5 +photo/horse/n02374451_8526.jpg 5 +photo/horse/n02374451_8718.jpg 5 +photo/horse/n02374451_8744.jpg 5 +photo/horse/n02374451_9064.jpg 5 +photo/horse/n02374451_9443.jpg 5 +photo/horse/n02374451_9892.jpg 5 +photo/horse/n02374451_10081.jpg 5 +photo/horse/n02374451_10098.jpg 5 +photo/horse/n02374451_10331.jpg 5 +photo/horse/n02374451_10669.jpg 5 +photo/horse/n02374451_10761.jpg 5 +photo/horse/n02374451_10809.jpg 5 +photo/horse/n02374451_11479.jpg 5 +photo/horse/n02374451_11483.jpg 5 +photo/horse/n02374451_11492.jpg 5 +photo/horse/n02374451_11894.jpg 5 +photo/horse/n02374451_12128.jpg 5 +photo/horse/n02374451_12174.jpg 5 +photo/horse/n02374451_12225.jpg 5 +photo/horse/n02374451_12230.jpg 5 +photo/horse/n02374451_12250.jpg 5 +photo/horse/n02374451_12254.jpg 5 +photo/horse/n02374451_12418.jpg 5 +photo/horse/n02374451_12792.jpg 5 +photo/horse/n02374451_12847.jpg 5 +photo/horse/n02374451_13159.jpg 5 +photo/horse/n02374451_13718.jpg 5 +photo/horse/n02374451_14119.jpg 5 +photo/horse/n02374451_14233.jpg 5 +photo/horse/n02374451_14399.jpg 5 +photo/horse/n02374451_14425.jpg 5 +photo/horse/n02374451_14738.jpg 5 +photo/horse/n02374451_14846.jpg 5 +photo/horse/n02374451_15307.jpg 5 +photo/horse/n02374451_15440.jpg 5 +photo/horse/n02374451_15453.jpg 5 +photo/horse/n02374451_15669.jpg 5 +photo/horse/n02374451_16358.jpg 5 +photo/horse/n02374451_17384.jpg 5 +photo/horse/n02374451_17474.jpg 5 +photo/horse/n02374451_17634.jpg 5 +photo/horse/n02374451_18192.jpg 5 +photo/horse/n02374451_18570.jpg 5 +photo/horse/n02374451_18909.jpg 5 +photo/house/pic_243.jpg 6 +photo/house/pic_250.jpg 6 +photo/house/pic_249.jpg 6 +photo/house/pic_251.jpg 6 +photo/house/pic_252.jpg 6 +photo/house/pic_253.jpg 6 +photo/house/pic_256.jpg 6 +photo/house/pic_255.jpg 6 +photo/house/pic_257.jpg 6 +photo/house/pic_260.jpg 6 +photo/house/pic_032.jpg 6 +photo/house/pic_030.jpg 6 +photo/house/pic_033.jpg 6 +photo/house/pic_034.jpg 6 +photo/house/pic_035.jpg 6 +photo/house/pic_036.jpg 6 +photo/house/pic_037.jpg 6 +photo/house/pic_038.jpg 6 +photo/house/pic_039.jpg 6 +photo/house/pic_042.jpg 6 +photo/house/pic_041.jpg 6 +photo/house/pic_040.jpg 6 +photo/house/pic_045.jpg 6 +photo/house/pic_046.jpg 6 +photo/house/pic_044.jpg 6 +photo/house/pic_043.jpg 6 +photo/house/pic_047.jpg 6 +photo/house/pic_048.jpg 6 +photo/house/pic_049.jpg 6 +photo/house/pic_050.jpg 6 +photo/house/pic_058.jpg 6 +photo/house/pic_216.jpg 6 +photo/house/pic_217.jpg 6 +photo/house/pic_220.jpg 6 +photo/house/pic_221.jpg 6 +photo/house/pic_222.jpg 6 +photo/house/pic_223.jpg 6 +photo/house/pic_224.jpg 6 +photo/house/pic_225.jpg 6 +photo/house/pic_226.jpg 6 +photo/house/pic_228.jpg 6 +photo/house/pic_229.jpg 6 +photo/house/pic_230.jpg 6 +photo/house/pic_231.jpg 6 +photo/house/pic_232.jpg 6 +photo/house/pic_233.jpg 6 +photo/house/pic_234.jpg 6 +photo/house/pic_235.jpg 6 +photo/house/pic_236.jpg 6 +photo/house/pic_238.jpg 6 +photo/house/pic_237.jpg 6 +photo/house/pic_067.jpg 6 +photo/house/pic_062.jpg 6 +photo/house/pic_075.jpg 6 +photo/house/pic_078.jpg 6 +photo/house/pic_079.jpg 6 +photo/house/pic_070.jpg 6 +photo/house/pic_066.jpg 6 +photo/house/pic_088.jpg 6 +photo/house/pic_081.jpg 6 +photo/house/pic_091.jpg 6 +photo/house/pic_072.jpg 6 +photo/house/pic_093.jpg 6 +photo/house/pic_086.jpg 6 +photo/house/pic_098.jpg 6 +photo/house/pic_096.jpg 6 +photo/house/pic_095.jpg 6 +photo/house/pic_094.jpg 6 +photo/house/pic_092.jpg 6 +photo/house/pic_090.jpg 6 +photo/house/pic_097.jpg 6 +photo/house/pic_061.jpg 6 +photo/house/pic_060.jpg 6 +photo/house/pic_057.jpg 6 +photo/house/pic_051.jpg 6 +photo/house/pic_054.jpg 6 +photo/house/pic_053.jpg 6 +photo/house/pic_052.jpg 6 +photo/house/pic_063.jpg 6 +photo/house/pic_059.jpg 6 +photo/house/pic_055.jpg 6 +photo/house/pic_056.jpg 6 +photo/house/pic_082.jpg 6 +photo/house/pic_080.jpg 6 +photo/house/pic_077.jpg 6 +photo/house/pic_076.jpg 6 +photo/house/pic_074.jpg 6 +photo/house/pic_073.jpg 6 +photo/house/pic_071.jpg 6 +photo/house/pic_069.jpg 6 +photo/house/pic_068.jpg 6 +photo/house/pic_065.jpg 6 +photo/house/pic_153.jpg 6 +photo/house/pic_156.jpg 6 +photo/house/pic_157.jpg 6 +photo/house/pic_158.jpg 6 +photo/house/pic_159.jpg 6 +photo/house/pic_160.jpg 6 +photo/house/pic_162.jpg 6 +photo/house/pic_161.jpg 6 +photo/house/pic_166.jpg 6 +photo/house/pic_165.jpg 6 +photo/house/pic_163.jpg 6 +photo/house/pic_164.jpg 6 +photo/house/pic_167.jpg 6 +photo/house/pic_168.jpg 6 +photo/house/pic_170.jpg 6 +photo/house/pic_169.jpg 6 +photo/house/pic_171.jpg 6 +photo/house/pic_172.jpg 6 +photo/house/pic_174.jpg 6 +photo/house/pic_175.jpg 6 +photo/house/pic_173.jpg 6 +photo/house/pic_134.jpg 6 +photo/house/pic_135.jpg 6 +photo/house/pic_136.jpg 6 +photo/house/pic_138.jpg 6 +photo/house/pic_139.jpg 6 +photo/house/pic_137.jpg 6 +photo/house/pic_140.jpg 6 +photo/house/pic_141.jpg 6 +photo/house/pic_143.jpg 6 +photo/house/pic_142.jpg 6 +photo/house/pic_144.jpg 6 +photo/house/pic_146.jpg 6 +photo/house/pic_145.jpg 6 +photo/house/pic_147.jpg 6 +photo/house/pic_148.jpg 6 +photo/house/pic_149.jpg 6 +photo/house/pic_150.jpg 6 +photo/house/pic_151.jpg 6 +photo/house/pic_154.jpg 6 +photo/house/pic_155.jpg 6 +photo/house/pic_197.jpg 6 +photo/house/pic_199.jpg 6 +photo/house/pic_200.jpg 6 +photo/house/pic_198.jpg 6 +photo/house/pic_202.jpg 6 +photo/house/pic_201.jpg 6 +photo/house/pic_204.jpg 6 +photo/house/pic_205.jpg 6 +photo/house/pic_203.jpg 6 +photo/house/pic_207.jpg 6 +photo/house/pic_206.jpg 6 +photo/house/pic_209.jpg 6 +photo/house/pic_208.jpg 6 +photo/house/pic_210.jpg 6 +photo/house/pic_211.jpg 6 +photo/house/pic_214.jpg 6 +photo/house/pic_213.jpg 6 +photo/house/pic_215.jpg 6 +photo/house/pic_219.jpg 6 +photo/house/pic_218.jpg 6 +photo/house/pic_280.jpg 6 +photo/house/pic_276.jpg 6 +photo/house/pic_287.jpg 6 +photo/house/pic_282.jpg 6 +photo/house/pic_283.jpg 6 +photo/house/pic_288.jpg 6 +photo/house/pic_289.jpg 6 +photo/house/pic_290.jpg 6 +photo/house/pic_281.jpg 6 +photo/house/pic_284.jpg 6 +photo/house/pic_089.jpg 6 +photo/house/pic_084.jpg 6 +photo/house/pic_085.jpg 6 +photo/house/pic_083.jpg 6 +photo/house/pic_099.jpg 6 +photo/house/pic_087.jpg 6 +photo/house/pic_106.jpg 6 +photo/house/pic_104.jpg 6 +photo/house/pic_103.jpg 6 +photo/house/pic_102.jpg 6 +photo/house/pic_101.jpg 6 +photo/house/pic_100.jpg 6 +photo/house/pic_110.jpg 6 +photo/house/pic_109.jpg 6 +photo/house/pic_108.jpg 6 +photo/house/pic_107.jpg 6 +photo/house/pic_111.jpg 6 +photo/house/pic_112.jpg 6 +photo/house/pic_113.jpg 6 +photo/house/pic_114.jpg 6 +photo/house/pic_262.jpg 6 +photo/house/pic_259.jpg 6 +photo/house/pic_264.jpg 6 +photo/house/pic_263.jpg 6 +photo/house/pic_265.jpg 6 +photo/house/pic_261.jpg 6 +photo/house/pic_266.jpg 6 +photo/house/pic_267.jpg 6 +photo/house/pic_269.jpg 6 +photo/house/pic_270.jpg 6 +photo/house/pic_268.jpg 6 +photo/house/pic_279.jpg 6 +photo/house/pic_278.jpg 6 +photo/house/pic_277.jpg 6 +photo/house/pic_275.jpg 6 +photo/house/pic_272.jpg 6 +photo/house/pic_274.jpg 6 +photo/house/pic_273.jpg 6 +photo/house/pic_271.jpg 6 +photo/house/pic_286.jpg 6 +photo/house/pic_285.jpg 6 +photo/house/pic_116.jpg 6 +photo/house/pic_115.jpg 6 +photo/house/pic_117.jpg 6 +photo/house/pic_118.jpg 6 +photo/house/pic_120.jpg 6 +photo/house/pic_119.jpg 6 +photo/house/pic_121.jpg 6 +photo/house/pic_122.jpg 6 +photo/house/pic_124.jpg 6 +photo/house/pic_123.jpg 6 +photo/house/pic_125.jpg 6 +photo/house/pic_126.jpg 6 +photo/house/pic_127.jpg 6 +photo/house/pic_128.jpg 6 +photo/house/pic_129.jpg 6 +photo/house/pic_130.jpg 6 +photo/house/pic_131.jpg 6 +photo/house/pic_132.jpg 6 +photo/house/pic_133.jpg 6 +photo/house/pic_001.jpg 6 +photo/house/pic_002.jpg 6 +photo/house/pic_003.jpg 6 +photo/house/pic_004.jpg 6 +photo/house/pic_005.jpg 6 +photo/house/pic_006.jpg 6 +photo/house/pic_007.jpg 6 +photo/house/pic_008.jpg 6 +photo/house/pic_178.jpg 6 +photo/house/pic_177.jpg 6 +photo/house/pic_176.jpg 6 +photo/house/pic_179.jpg 6 +photo/house/pic_181.jpg 6 +photo/house/pic_180.jpg 6 +photo/house/pic_185.jpg 6 +photo/house/pic_183.jpg 6 +photo/house/pic_184.jpg 6 +photo/house/pic_190.jpg 6 +photo/house/pic_188.jpg 6 +photo/house/pic_189.jpg 6 +photo/house/pic_186.jpg 6 +photo/house/pic_187.jpg 6 +photo/house/pic_191.jpg 6 +photo/house/pic_192.jpg 6 +photo/house/pic_194.jpg 6 +photo/house/pic_193.jpg 6 +photo/house/pic_195.jpg 6 +photo/house/pic_196.jpg 6 +photo/person/253_0045.jpg 7 +photo/person/253_0046.jpg 7 +photo/person/253_0047.jpg 7 +photo/person/253_0048.jpg 7 +photo/person/253_0049.jpg 7 +photo/person/253_0050.jpg 7 +photo/person/253_0051.jpg 7 +photo/person/253_0052.jpg 7 +photo/person/253_0053.jpg 7 +photo/person/253_0054.jpg 7 +photo/person/253_0055.jpg 7 +photo/person/253_0056.jpg 7 +photo/person/253_0057.jpg 7 +photo/person/253_0058.jpg 7 +photo/person/253_0059.jpg 7 +photo/person/253_0060.jpg 7 +photo/person/253_0061.jpg 7 +photo/person/253_0062.jpg 7 +photo/person/253_0063.jpg 7 +photo/person/253_0064.jpg 7 +photo/person/253_0065.jpg 7 +photo/person/253_0066.jpg 7 +photo/person/253_0067.jpg 7 +photo/person/253_0068.jpg 7 +photo/person/253_0069.jpg 7 +photo/person/253_0070.jpg 7 +photo/person/253_0071.jpg 7 +photo/person/253_0072.jpg 7 +photo/person/253_0073.jpg 7 +photo/person/253_0074.jpg 7 +photo/person/253_0075.jpg 7 +photo/person/253_0076.jpg 7 +photo/person/253_0077.jpg 7 +photo/person/253_0078.jpg 7 +photo/person/253_0079.jpg 7 +photo/person/253_0080.jpg 7 +photo/person/253_0081.jpg 7 +photo/person/253_0082.jpg 7 +photo/person/253_0083.jpg 7 +photo/person/253_0084.jpg 7 +photo/person/253_0085.jpg 7 +photo/person/253_0086.jpg 7 +photo/person/253_0087.jpg 7 +photo/person/253_0088.jpg 7 +photo/person/253_0089.jpg 7 +photo/person/253_0090.jpg 7 +photo/person/253_0091.jpg 7 +photo/person/253_0092.jpg 7 +photo/person/253_0093.jpg 7 +photo/person/253_0094.jpg 7 +photo/person/253_0095.jpg 7 +photo/person/253_0096.jpg 7 +photo/person/253_0097.jpg 7 +photo/person/253_0098.jpg 7 +photo/person/253_0099.jpg 7 +photo/person/253_0100.jpg 7 +photo/person/253_0101.jpg 7 +photo/person/253_0102.jpg 7 +photo/person/253_0103.jpg 7 +photo/person/253_0104.jpg 7 +photo/person/253_0105.jpg 7 +photo/person/253_0106.jpg 7 +photo/person/253_0107.jpg 7 +photo/person/253_0108.jpg 7 +photo/person/253_0109.jpg 7 +photo/person/253_0110.jpg 7 +photo/person/253_0111.jpg 7 +photo/person/253_0112.jpg 7 +photo/person/253_0113.jpg 7 +photo/person/253_0114.jpg 7 +photo/person/253_0115.jpg 7 +photo/person/253_0116.jpg 7 +photo/person/253_0117.jpg 7 +photo/person/253_0118.jpg 7 +photo/person/253_0119.jpg 7 +photo/person/253_0120.jpg 7 +photo/person/253_0121.jpg 7 +photo/person/253_0122.jpg 7 +photo/person/253_0123.jpg 7 +photo/person/253_0124.jpg 7 +photo/person/253_0125.jpg 7 +photo/person/253_0126.jpg 7 +photo/person/253_0127.jpg 7 +photo/person/253_0128.jpg 7 +photo/person/253_0129.jpg 7 +photo/person/253_0130.jpg 7 +photo/person/253_0131.jpg 7 +photo/person/253_0132.jpg 7 +photo/person/253_0133.jpg 7 +photo/person/253_0134.jpg 7 +photo/person/253_0135.jpg 7 +photo/person/253_0136.jpg 7 +photo/person/253_0137.jpg 7 +photo/person/253_0138.jpg 7 +photo/person/253_0139.jpg 7 +photo/person/253_0140.jpg 7 +photo/person/253_0141.jpg 7 +photo/person/253_0142.jpg 7 +photo/person/253_0143.jpg 7 +photo/person/253_0144.jpg 7 +photo/person/253_0145.jpg 7 +photo/person/253_0146.jpg 7 +photo/person/253_0147.jpg 7 +photo/person/253_0148.jpg 7 +photo/person/253_0149.jpg 7 +photo/person/253_0150.jpg 7 +photo/person/253_0151.jpg 7 +photo/person/253_0152.jpg 7 +photo/person/253_0153.jpg 7 +photo/person/253_0154.jpg 7 +photo/person/253_0155.jpg 7 +photo/person/253_0156.jpg 7 +photo/person/253_0157.jpg 7 +photo/person/253_0158.jpg 7 +photo/person/253_0159.jpg 7 +photo/person/253_0160.jpg 7 +photo/person/253_0161.jpg 7 +photo/person/253_0162.jpg 7 +photo/person/253_0163.jpg 7 +photo/person/253_0164.jpg 7 +photo/person/253_0165.jpg 7 +photo/person/253_0166.jpg 7 +photo/person/253_0167.jpg 7 +photo/person/253_0168.jpg 7 +photo/person/253_0169.jpg 7 +photo/person/253_0170.jpg 7 +photo/person/253_0171.jpg 7 +photo/person/253_0172.jpg 7 +photo/person/253_0173.jpg 7 +photo/person/253_0174.jpg 7 +photo/person/253_0175.jpg 7 +photo/person/253_0176.jpg 7 +photo/person/253_0177.jpg 7 +photo/person/253_0178.jpg 7 +photo/person/253_0179.jpg 7 +photo/person/253_0180.jpg 7 +photo/person/253_0181.jpg 7 +photo/person/253_0182.jpg 7 +photo/person/253_0183.jpg 7 +photo/person/253_0184.jpg 7 +photo/person/253_0185.jpg 7 +photo/person/253_0186.jpg 7 +photo/person/253_0187.jpg 7 +photo/person/253_0188.jpg 7 +photo/person/253_0189.jpg 7 +photo/person/253_0190.jpg 7 +photo/person/253_0191.jpg 7 +photo/person/253_0192.jpg 7 +photo/person/253_0193.jpg 7 +photo/person/253_0194.jpg 7 +photo/person/253_0195.jpg 7 +photo/person/253_0196.jpg 7 +photo/person/253_0197.jpg 7 +photo/person/253_0198.jpg 7 +photo/person/253_0199.jpg 7 +photo/person/253_0200.jpg 7 +photo/person/253_0201.jpg 7 +photo/person/253_0202.jpg 7 +photo/person/253_0203.jpg 7 +photo/person/253_0204.jpg 7 +photo/person/253_0205.jpg 7 +photo/person/253_0206.jpg 7 +photo/person/253_0207.jpg 7 +photo/person/253_0208.jpg 7 +photo/person/253_0209.jpg 7 +photo/person/253_0210.jpg 7 +photo/person/253_0211.jpg 7 +photo/person/253_0212.jpg 7 +photo/person/253_0213.jpg 7 +photo/person/253_0214.jpg 7 +photo/person/253_0215.jpg 7 +photo/person/253_0216.jpg 7 +photo/person/253_0217.jpg 7 +photo/person/253_0218.jpg 7 +photo/person/253_0219.jpg 7 +photo/person/253_0220.jpg 7 +photo/person/253_0221.jpg 7 +photo/person/253_0222.jpg 7 +photo/person/253_0223.jpg 7 +photo/person/253_0224.jpg 7 +photo/person/253_0225.jpg 7 +photo/person/253_0226.jpg 7 +photo/person/253_0227.jpg 7 +photo/person/253_0228.jpg 7 +photo/person/253_0229.jpg 7 +photo/person/253_0230.jpg 7 +photo/person/253_0231.jpg 7 +photo/person/253_0232.jpg 7 +photo/person/253_0233.jpg 7 +photo/person/253_0234.jpg 7 +photo/person/253_0235.jpg 7 +photo/person/253_0236.jpg 7 +photo/person/253_0237.jpg 7 +photo/person/253_0238.jpg 7 +photo/person/253_0239.jpg 7 +photo/person/253_0240.jpg 7 +photo/person/253_0241.jpg 7 +photo/person/253_0242.jpg 7 +photo/person/253_0243.jpg 7 +photo/person/253_0244.jpg 7 +photo/person/253_0245.jpg 7 +photo/person/253_0246.jpg 7 +photo/person/253_0247.jpg 7 +photo/person/253_0248.jpg 7 +photo/person/253_0249.jpg 7 +photo/person/253_0250.jpg 7 +photo/person/253_0251.jpg 7 +photo/person/253_0252.jpg 7 +photo/person/253_0253.jpg 7 +photo/person/253_0254.jpg 7 +photo/person/253_0255.jpg 7 +photo/person/253_0256.jpg 7 +photo/person/253_0257.jpg 7 +photo/person/253_0258.jpg 7 +photo/person/253_0259.jpg 7 +photo/person/253_0260.jpg 7 +photo/person/253_0261.jpg 7 +photo/person/253_0262.jpg 7 +photo/person/253_0263.jpg 7 +photo/person/253_0264.jpg 7 +photo/person/253_0265.jpg 7 +photo/person/253_0266.jpg 7 +photo/person/253_0267.jpg 7 +photo/person/253_0268.jpg 7 +photo/person/253_0269.jpg 7 +photo/person/253_0270.jpg 7 +photo/person/253_0271.jpg 7 +photo/person/253_0272.jpg 7 +photo/person/253_0273.jpg 7 +photo/person/253_0274.jpg 7 +photo/person/253_0275.jpg 7 +photo/person/253_0276.jpg 7 +photo/person/253_0277.jpg 7 +photo/person/253_0278.jpg 7 +photo/person/253_0279.jpg 7 +photo/person/253_0280.jpg 7 +photo/person/253_0281.jpg 7 +photo/person/253_0282.jpg 7 +photo/person/253_0283.jpg 7 +photo/person/253_0284.jpg 7 +photo/person/253_0285.jpg 7 +photo/person/253_0286.jpg 7 +photo/person/253_0287.jpg 7 +photo/person/253_0288.jpg 7 +photo/person/253_0289.jpg 7 +photo/person/253_0290.jpg 7 +photo/person/253_0291.jpg 7 +photo/person/253_0292.jpg 7 +photo/person/253_0293.jpg 7 +photo/person/253_0294.jpg 7 +photo/person/253_0295.jpg 7 +photo/person/253_0296.jpg 7 +photo/person/253_0297.jpg 7 +photo/person/253_0298.jpg 7 +photo/person/253_0299.jpg 7 +photo/person/253_0300.jpg 7 +photo/person/253_0301.jpg 7 +photo/person/253_0302.jpg 7 +photo/person/253_0303.jpg 7 +photo/person/253_0304.jpg 7 +photo/person/253_0305.jpg 7 +photo/person/253_0306.jpg 7 +photo/person/253_0307.jpg 7 +photo/person/253_0308.jpg 7 +photo/person/253_0309.jpg 7 +photo/person/253_0310.jpg 7 +photo/person/253_0311.jpg 7 +photo/person/253_0312.jpg 7 +photo/person/253_0313.jpg 7 +photo/person/253_0314.jpg 7 +photo/person/253_0315.jpg 7 +photo/person/253_0316.jpg 7 +photo/person/253_0317.jpg 7 +photo/person/253_0318.jpg 7 +photo/person/253_0319.jpg 7 +photo/person/253_0320.jpg 7 +photo/person/253_0321.jpg 7 +photo/person/253_0322.jpg 7 +photo/person/253_0323.jpg 7 +photo/person/253_0324.jpg 7 +photo/person/253_0325.jpg 7 +photo/person/253_0326.jpg 7 +photo/person/253_0327.jpg 7 +photo/person/253_0328.jpg 7 +photo/person/253_0329.jpg 7 +photo/person/253_0330.jpg 7 +photo/person/253_0331.jpg 7 +photo/person/253_0332.jpg 7 +photo/person/253_0333.jpg 7 +photo/person/253_0334.jpg 7 +photo/person/253_0335.jpg 7 +photo/person/253_0336.jpg 7 +photo/person/253_0337.jpg 7 +photo/person/253_0338.jpg 7 +photo/person/253_0339.jpg 7 +photo/person/253_0340.jpg 7 +photo/person/253_0341.jpg 7 +photo/person/253_0342.jpg 7 +photo/person/253_0343.jpg 7 +photo/person/253_0344.jpg 7 +photo/person/253_0345.jpg 7 +photo/person/253_0346.jpg 7 +photo/person/253_0347.jpg 7 +photo/person/253_0348.jpg 7 +photo/person/253_0349.jpg 7 +photo/person/253_0350.jpg 7 +photo/person/253_0351.jpg 7 +photo/person/253_0352.jpg 7 +photo/person/253_0353.jpg 7 +photo/person/253_0354.jpg 7 +photo/person/253_0355.jpg 7 +photo/person/253_0356.jpg 7 +photo/person/253_0357.jpg 7 +photo/person/253_0358.jpg 7 +photo/person/253_0359.jpg 7 +photo/person/253_0360.jpg 7 +photo/person/253_0361.jpg 7 +photo/person/253_0362.jpg 7 +photo/person/253_0363.jpg 7 +photo/person/253_0364.jpg 7 +photo/person/253_0365.jpg 7 +photo/person/253_0366.jpg 7 +photo/person/253_0367.jpg 7 +photo/person/253_0368.jpg 7 +photo/person/253_0369.jpg 7 +photo/person/253_0370.jpg 7 +photo/person/253_0371.jpg 7 +photo/person/253_0372.jpg 7 +photo/person/253_0373.jpg 7 +photo/person/253_0374.jpg 7 +photo/person/253_0375.jpg 7 +photo/person/253_0376.jpg 7 +photo/person/253_0377.jpg 7 +photo/person/253_0378.jpg 7 +photo/person/253_0379.jpg 7 +photo/person/253_0380.jpg 7 +photo/person/253_0381.jpg 7 +photo/person/253_0382.jpg 7 +photo/person/253_0383.jpg 7 +photo/person/253_0384.jpg 7 +photo/person/253_0385.jpg 7 +photo/person/253_0386.jpg 7 +photo/person/253_0387.jpg 7 +photo/person/253_0388.jpg 7 +photo/person/253_0390.jpg 7 +photo/person/253_0393.jpg 7 +photo/person/253_0394.jpg 7 +photo/person/253_0395.jpg 7 +photo/person/253_0396.jpg 7 +photo/person/253_0397.jpg 7 +photo/person/253_0398.jpg 7 +photo/person/253_0399.jpg 7 +photo/person/253_0400.jpg 7 +photo/person/253_0401.jpg 7 +photo/person/253_0402.jpg 7 +photo/person/253_0403.jpg 7 +photo/person/253_0404.jpg 7 +photo/person/253_0405.jpg 7 +photo/person/253_0406.jpg 7 +photo/person/253_0407.jpg 7 +photo/person/253_0408.jpg 7 +photo/person/253_0409.jpg 7 +photo/person/253_0410.jpg 7 +photo/person/253_0411.jpg 7 +photo/person/253_0412.jpg 7 +photo/person/253_0413.jpg 7 +photo/person/253_0414.jpg 7 +photo/person/253_0415.jpg 7 +photo/person/253_0416.jpg 7 +photo/person/253_0417.jpg 7 +photo/person/253_0418.jpg 7 +photo/person/253_0419.jpg 7 +photo/person/253_0420.jpg 7 +photo/person/253_0421.jpg 7 +photo/person/253_0422.jpg 7 +photo/person/253_0423.jpg 7 +photo/person/253_0424.jpg 7 +photo/person/253_0425.jpg 7 +photo/person/253_0426.jpg 7 +photo/person/253_0427.jpg 7 +photo/person/253_0428.jpg 7 +photo/person/253_0429.jpg 7 +photo/person/253_0430.jpg 7 +photo/person/253_0431.jpg 7 +photo/person/253_0432.jpg 7 +photo/person/253_0433.jpg 7 +photo/person/253_0434.jpg 7 +photo/person/253_0435.jpg 7 diff --git a/domainlab/zdata/pacs_split/readme.txt b/domainlab/zdata/pacs_split/readme.txt new file mode 100644 index 000000000..36a00efc7 --- /dev/null +++ b/domainlab/zdata/pacs_split/readme.txt @@ -0,0 +1,10 @@ + +1. The h5py files was pre-read using cv2, so it is BGR channel order. +2. This benckmark is sensitive to the different train val splits, so please use this train val splits for the fair comparisons. + +https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd + +[https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd](https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd) + + +https://github.com/facebookresearch/DomainBed/blob/4294ec699df761b46a1505734f6be16ef009cad9/domainbed/scripts/download.py#L29 diff --git a/domainlab/zdata/pacs_split/sketch_10.txt b/domainlab/zdata/pacs_split/sketch_10.txt new file mode 100644 index 000000000..79f855d52 --- /dev/null +++ b/domainlab/zdata/pacs_split/sketch_10.txt @@ -0,0 +1,10 @@ +sketch/house/8873.png 6 +sketch/guitar/n03467517_6423-3.png 4 +sketch/elephant/5981.png 2 +sketch/dog/n02103406_3255-6.png 1 +sketch/horse/n02374451_779-1.png 5 +sketch/guitar/n02676566_8618-2.png 4 +sketch/elephant/n02503517_12688-4.png 2 +sketch/dog/5302.png 1 +sketch/giraffe/n02439033_13384-2.png 3 +sketch/dog/5317.png 1 diff --git a/domainlab/zdata/pacs_split/sketch_100.txt b/domainlab/zdata/pacs_split/sketch_100.txt new file mode 100644 index 000000000..2856e053f --- /dev/null +++ b/domainlab/zdata/pacs_split/sketch_100.txt @@ -0,0 +1,100 @@ +sketch/guitar/n02676566_6704-1.png 4 +sketch/dog/5356.png 1 +sketch/dog/n02103406_3743-4.png 1 +sketch/person/12197.png 7 +sketch/person/12198.png 7 +sketch/person/12133.png 7 +sketch/elephant/n02503517_6937-1.png 2 +sketch/horse/8537.png 5 +sketch/horse/8527.png 5 +sketch/horse/n02374451_14425-8.png 5 +sketch/giraffe/n02439033_8875-1.png 3 +sketch/dog/n02106662_466-2.png 1 +sketch/guitar/n03272010_1708-4.png 4 +sketch/dog/n02103406_6688-9.png 1 +sketch/horse/n02374451_3388-8.png 5 +sketch/elephant/n02503517_4253-3.png 2 +sketch/giraffe/n02439033_14600-1.png 3 +sketch/elephant/n02503517_9241-3.png 2 +sketch/giraffe/n02439033_11215-2.png 3 +sketch/elephant/n02503517_1415-2.png 2 +sketch/dog/n02106662_2157-2.png 1 +sketch/elephant/n02503517_4253-5.png 2 +sketch/giraffe/n02439033_14040-4.png 3 +sketch/elephant/n02503517_5905-8.png 2 +sketch/guitar/n03272010_6255-5.png 4 +sketch/horse/n02374451_10809-5.png 5 +sketch/giraffe/n02439033_8846-4.png 3 +sketch/person/12171.png 7 +sketch/elephant/n02503517_5267-3.png 2 +sketch/giraffe/n02439033_11504-4.png 3 +sketch/person/12131.png 7 +sketch/dog/n02109525_18347-4.png 1 +sketch/horse/n02374451_17634-1.png 5 +sketch/elephant/n02503517_8757-1.png 2 +sketch/guitar/n03467517_19701-2.png 4 +sketch/dog/n02106662_27393-2.png 1 +sketch/horse/n02374451_8065-4.png 5 +sketch/guitar/n02676566_6864-1.png 4 +sketch/elephant/n02503517_8901-2.png 2 +sketch/horse/n02374451_9892-3.png 5 +sketch/dog/n02106662_7960-1.png 1 +sketch/guitar/n03272010_9858-1.png 4 +sketch/guitar/n02676566_8467-1.png 4 +sketch/dog/n02103406_3108-6.png 1 +sketch/giraffe/n02439033_14781-3.png 3 +sketch/horse/8499.png 5 +sketch/guitar/n02676566_4469-2.png 4 +sketch/dog/n02109525_704-6.png 1 +sketch/dog/n02106662_24786-5.png 1 +sketch/guitar/n03467517_8929-1.png 4 +sketch/guitar/n03272010_6725-1.png 4 +sketch/giraffe/n02439033_11683-7.png 3 +sketch/elephant/n02503517_5117-1.png 2 +sketch/dog/n02106662_2101-9.png 1 +sketch/elephant/n02503517_10193-9.png 2 +sketch/horse/n02374451_18909-6.png 5 +sketch/guitar/n02676566_9254-1.png 4 +sketch/elephant/n02503517_2993-2.png 2 +sketch/horse/n02374451_1443-4.png 5 +sketch/elephant/n02503517_4413-3.png 2 +sketch/horse/n02374451_16948-1.png 5 +sketch/dog/n02106662_10406-3.png 1 +sketch/giraffe/n02439033_10164-2.png 3 +sketch/person/12210.png 7 +sketch/dog/n02106662_26549-6.png 1 +sketch/elephant/n02503517_10259-6.png 2 +sketch/elephant/n02503517_10558-4.png 2 +sketch/elephant/n02503517_3108-3.png 2 +sketch/giraffe/n02439033_13602-6.png 3 +sketch/elephant/n02503517_6429-3.png 2 +sketch/guitar/n02676566_2866-3.png 4 +sketch/horse/n02374451_12174-3.png 5 +sketch/dog/n02103406_3056-1.png 1 +sketch/giraffe/7410.png 3 +sketch/guitar/n02676566_6914-1.png 4 +sketch/giraffe/n02439033_11130-5.png 3 +sketch/giraffe/7425.png 3 +sketch/horse/n02374451_12418-10.png 5 +sketch/horse/n02374451_12847-5.png 5 +sketch/dog/n02106662_15858-1.png 1 +sketch/elephant/n02503517_8571-6.png 2 +sketch/giraffe/n02439033_14580-1.png 3 +sketch/giraffe/n02439033_11666-5.png 3 +sketch/guitar/n03272010_7383-4.png 4 +sketch/guitar/n02676566_3360-2.png 4 +sketch/guitar/n03272010_5483-1.png 4 +sketch/elephant/n02503517_10193-1.png 2 +sketch/giraffe/7440.png 3 +sketch/guitar/n03272010_7390-4.png 4 +sketch/dog/n02103406_2209-6.png 1 +sketch/elephant/n02503517_5892-4.png 2 +sketch/guitar/n02676566_6430-1.png 4 +sketch/giraffe/n02439033_9472-7.png 3 +sketch/guitar/n02676566_8618-6.png 4 +sketch/person/12134.png 7 +sketch/giraffe/n02439033_11627-5.png 3 +sketch/giraffe/n02439033_11059-8.png 3 +sketch/giraffe/n02439033_3944-10.png 3 +sketch/dog/n02103406_1754-3.png 1 +sketch/house/8812.png 6 diff --git a/domainlab/zdata/pacs_split/sketch_crossval_kfold.txt b/domainlab/zdata/pacs_split/sketch_crossval_kfold.txt new file mode 100644 index 000000000..63c0f2050 --- /dev/null +++ b/domainlab/zdata/pacs_split/sketch_crossval_kfold.txt @@ -0,0 +1,398 @@ +sketch/dog/n02103406_343-1.png 1 +sketch/dog/n02103406_343-2.png 1 +sketch/dog/n02103406_343-3.png 1 +sketch/dog/n02103406_343-4.png 1 +sketch/dog/n02103406_343-5.png 1 +sketch/dog/n02103406_343-6.png 1 +sketch/dog/n02103406_343-7.png 1 +sketch/dog/n02103406_343-8.png 1 +sketch/dog/n02103406_343-9.png 1 +sketch/dog/n02103406_346-1.png 1 +sketch/dog/n02103406_346-2.png 1 +sketch/dog/n02103406_346-3.png 1 +sketch/dog/n02103406_346-4.png 1 +sketch/dog/n02103406_346-5.png 1 +sketch/dog/n02103406_346-6.png 1 +sketch/dog/n02103406_346-7.png 1 +sketch/dog/n02103406_371-1.png 1 +sketch/dog/n02103406_371-2.png 1 +sketch/dog/n02103406_371-3.png 1 +sketch/dog/n02103406_371-4.png 1 +sketch/dog/n02103406_371-5.png 1 +sketch/dog/n02103406_371-6.png 1 +sketch/dog/n02103406_371-7.png 1 +sketch/dog/n02103406_371-8.png 1 +sketch/dog/n02103406_371-9.png 1 +sketch/dog/n02103406_371-10.png 1 +sketch/dog/n02103406_371-11.png 1 +sketch/dog/n02103406_651-1.png 1 +sketch/dog/n02103406_651-2.png 1 +sketch/dog/n02103406_651-3.png 1 +sketch/dog/n02103406_651-4.png 1 +sketch/dog/n02103406_651-5.png 1 +sketch/dog/n02103406_651-6.png 1 +sketch/dog/n02103406_651-7.png 1 +sketch/dog/n02103406_865-1.png 1 +sketch/dog/n02103406_865-2.png 1 +sketch/dog/n02103406_865-3.png 1 +sketch/dog/n02103406_865-4.png 1 +sketch/dog/n02103406_865-5.png 1 +sketch/dog/n02103406_865-6.png 1 +sketch/dog/n02103406_865-7.png 1 +sketch/dog/n02103406_865-8.png 1 +sketch/dog/n02103406_865-9.png 1 +sketch/dog/n02103406_865-10.png 1 +sketch/dog/n02103406_865-11.png 1 +sketch/dog/n02103406_936-1.png 1 +sketch/dog/n02103406_936-2.png 1 +sketch/dog/n02103406_936-3.png 1 +sketch/dog/n02103406_936-4.png 1 +sketch/dog/n02103406_936-5.png 1 +sketch/dog/n02103406_936-6.png 1 +sketch/dog/n02103406_936-7.png 1 +sketch/dog/n02103406_936-8.png 1 +sketch/dog/n02103406_936-9.png 1 +sketch/dog/n02103406_995-1.png 1 +sketch/dog/n02103406_995-2.png 1 +sketch/dog/n02103406_995-3.png 1 +sketch/dog/n02103406_995-4.png 1 +sketch/dog/n02103406_995-5.png 1 +sketch/dog/n02103406_995-6.png 1 +sketch/dog/n02103406_1011-1.png 1 +sketch/dog/n02103406_1011-2.png 1 +sketch/dog/n02103406_1011-3.png 1 +sketch/dog/n02103406_1011-4.png 1 +sketch/dog/n02103406_1011-5.png 1 +sketch/dog/n02103406_1138-1.png 1 +sketch/dog/n02103406_1138-2.png 1 +sketch/dog/n02103406_1138-3.png 1 +sketch/dog/n02103406_1138-4.png 1 +sketch/dog/n02103406_1138-5.png 1 +sketch/dog/n02103406_1138-6.png 1 +sketch/dog/n02103406_1138-7.png 1 +sketch/dog/n02103406_1138-8.png 1 +sketch/dog/n02103406_1170-1.png 1 +sketch/dog/n02103406_1170-2.png 1 +sketch/dog/n02103406_1170-3.png 1 +sketch/dog/n02103406_1170-4.png 1 +sketch/dog/n02103406_1170-5.png 1 +sketch/elephant/n02503517_79-1.png 2 +sketch/elephant/n02503517_79-2.png 2 +sketch/elephant/n02503517_79-3.png 2 +sketch/elephant/n02503517_79-4.png 2 +sketch/elephant/n02503517_79-5.png 2 +sketch/elephant/n02503517_86-1.png 2 +sketch/elephant/n02503517_86-2.png 2 +sketch/elephant/n02503517_86-3.png 2 +sketch/elephant/n02503517_86-4.png 2 +sketch/elephant/n02503517_86-5.png 2 +sketch/elephant/n02503517_86-6.png 2 +sketch/elephant/n02503517_184-1.png 2 +sketch/elephant/n02503517_184-2.png 2 +sketch/elephant/n02503517_184-3.png 2 +sketch/elephant/n02503517_184-4.png 2 +sketch/elephant/n02503517_184-5.png 2 +sketch/elephant/n02503517_184-6.png 2 +sketch/elephant/n02503517_184-7.png 2 +sketch/elephant/n02503517_184-8.png 2 +sketch/elephant/n02503517_184-9.png 2 +sketch/elephant/n02503517_194-1.png 2 +sketch/elephant/n02503517_194-2.png 2 +sketch/elephant/n02503517_194-3.png 2 +sketch/elephant/n02503517_194-4.png 2 +sketch/elephant/n02503517_194-5.png 2 +sketch/elephant/n02503517_194-6.png 2 +sketch/elephant/n02503517_311-1.png 2 +sketch/elephant/n02503517_311-2.png 2 +sketch/elephant/n02503517_311-3.png 2 +sketch/elephant/n02503517_311-4.png 2 +sketch/elephant/n02503517_311-5.png 2 +sketch/elephant/n02503517_311-6.png 2 +sketch/elephant/n02503517_564-1.png 2 +sketch/elephant/n02503517_564-2.png 2 +sketch/elephant/n02503517_564-3.png 2 +sketch/elephant/n02503517_564-4.png 2 +sketch/elephant/n02503517_564-5.png 2 +sketch/elephant/n02503517_753-1.png 2 +sketch/elephant/n02503517_753-2.png 2 +sketch/elephant/n02503517_753-3.png 2 +sketch/elephant/n02503517_753-4.png 2 +sketch/elephant/n02503517_753-5.png 2 +sketch/elephant/n02503517_753-6.png 2 +sketch/elephant/n02503517_759-1.png 2 +sketch/elephant/n02503517_759-2.png 2 +sketch/elephant/n02503517_759-3.png 2 +sketch/elephant/n02503517_759-4.png 2 +sketch/elephant/n02503517_759-5.png 2 +sketch/elephant/n02503517_759-6.png 2 +sketch/elephant/n02503517_759-7.png 2 +sketch/elephant/n02503517_759-8.png 2 +sketch/elephant/n02503517_792-1.png 2 +sketch/elephant/n02503517_792-2.png 2 +sketch/elephant/n02503517_792-3.png 2 +sketch/elephant/n02503517_792-4.png 2 +sketch/elephant/n02503517_792-5.png 2 +sketch/elephant/n02503517_1292-1.png 2 +sketch/elephant/n02503517_1292-2.png 2 +sketch/elephant/n02503517_1292-3.png 2 +sketch/elephant/n02503517_1292-4.png 2 +sketch/elephant/n02503517_1292-5.png 2 +sketch/elephant/n02503517_1292-6.png 2 +sketch/elephant/n02503517_1292-7.png 2 +sketch/elephant/n02503517_1359-1.png 2 +sketch/elephant/n02503517_1359-2.png 2 +sketch/elephant/n02503517_1359-3.png 2 +sketch/elephant/n02503517_1359-4.png 2 +sketch/elephant/n02503517_1359-5.png 2 +sketch/elephant/n02503517_1359-6.png 2 +sketch/elephant/n02503517_1383-1.png 2 +sketch/elephant/n02503517_1383-2.png 2 +sketch/elephant/n02503517_1383-3.png 2 +sketch/elephant/n02503517_1383-4.png 2 +sketch/elephant/n02503517_1383-5.png 2 +sketch/elephant/n02503517_1383-6.png 2 +sketch/giraffe/n02439033_67-1.png 3 +sketch/giraffe/n02439033_67-2.png 3 +sketch/giraffe/n02439033_67-3.png 3 +sketch/giraffe/n02439033_67-4.png 3 +sketch/giraffe/n02439033_67-5.png 3 +sketch/giraffe/n02439033_67-6.png 3 +sketch/giraffe/n02439033_67-7.png 3 +sketch/giraffe/n02439033_221-1.png 3 +sketch/giraffe/n02439033_221-2.png 3 +sketch/giraffe/n02439033_221-3.png 3 +sketch/giraffe/n02439033_221-4.png 3 +sketch/giraffe/n02439033_221-5.png 3 +sketch/giraffe/n02439033_221-6.png 3 +sketch/giraffe/n02439033_376-1.png 3 +sketch/giraffe/n02439033_376-2.png 3 +sketch/giraffe/n02439033_376-3.png 3 +sketch/giraffe/n02439033_376-4.png 3 +sketch/giraffe/n02439033_376-5.png 3 +sketch/giraffe/n02439033_569-1.png 3 +sketch/giraffe/n02439033_569-2.png 3 +sketch/giraffe/n02439033_569-3.png 3 +sketch/giraffe/n02439033_569-4.png 3 +sketch/giraffe/n02439033_569-5.png 3 +sketch/giraffe/n02439033_628-1.png 3 +sketch/giraffe/n02439033_628-2.png 3 +sketch/giraffe/n02439033_628-3.png 3 +sketch/giraffe/n02439033_628-4.png 3 +sketch/giraffe/n02439033_628-5.png 3 +sketch/giraffe/n02439033_628-6.png 3 +sketch/giraffe/n02439033_628-7.png 3 +sketch/giraffe/n02439033_628-8.png 3 +sketch/giraffe/n02439033_628-9.png 3 +sketch/giraffe/n02439033_628-10.png 3 +sketch/giraffe/n02439033_866-1.png 3 +sketch/giraffe/n02439033_866-2.png 3 +sketch/giraffe/n02439033_866-3.png 3 +sketch/giraffe/n02439033_866-4.png 3 +sketch/giraffe/n02439033_866-5.png 3 +sketch/giraffe/n02439033_866-6.png 3 +sketch/giraffe/n02439033_991-1.png 3 +sketch/giraffe/n02439033_991-2.png 3 +sketch/giraffe/n02439033_991-3.png 3 +sketch/giraffe/n02439033_991-4.png 3 +sketch/giraffe/n02439033_991-5.png 3 +sketch/giraffe/n02439033_991-6.png 3 +sketch/giraffe/n02439033_991-7.png 3 +sketch/giraffe/n02439033_991-8.png 3 +sketch/giraffe/n02439033_991-9.png 3 +sketch/giraffe/n02439033_1327-1.png 3 +sketch/giraffe/n02439033_1327-2.png 3 +sketch/giraffe/n02439033_1327-3.png 3 +sketch/giraffe/n02439033_1327-4.png 3 +sketch/giraffe/n02439033_1327-5.png 3 +sketch/giraffe/n02439033_1508-1.png 3 +sketch/giraffe/n02439033_1508-2.png 3 +sketch/giraffe/n02439033_1508-3.png 3 +sketch/giraffe/n02439033_1508-4.png 3 +sketch/giraffe/n02439033_1508-5.png 3 +sketch/giraffe/n02439033_1508-6.png 3 +sketch/giraffe/n02439033_1508-7.png 3 +sketch/giraffe/n02439033_1508-8.png 3 +sketch/giraffe/n02439033_1508-9.png 3 +sketch/giraffe/n02439033_2486-1.png 3 +sketch/giraffe/n02439033_2486-2.png 3 +sketch/giraffe/n02439033_2486-3.png 3 +sketch/giraffe/n02439033_2486-4.png 3 +sketch/giraffe/n02439033_2486-5.png 3 +sketch/giraffe/n02439033_2486-6.png 3 +sketch/giraffe/n02439033_2500-1.png 3 +sketch/giraffe/n02439033_2500-2.png 3 +sketch/giraffe/n02439033_2500-3.png 3 +sketch/giraffe/n02439033_2500-4.png 3 +sketch/giraffe/n02439033_2500-5.png 3 +sketch/giraffe/n02439033_2500-6.png 3 +sketch/giraffe/n02439033_2677-1.png 3 +sketch/giraffe/n02439033_2677-2.png 3 +sketch/guitar/7601.png 4 +sketch/guitar/7602.png 4 +sketch/guitar/7603.png 4 +sketch/guitar/7604.png 4 +sketch/guitar/7605.png 4 +sketch/guitar/7606.png 4 +sketch/guitar/7607.png 4 +sketch/guitar/7608.png 4 +sketch/guitar/7609.png 4 +sketch/guitar/7610.png 4 +sketch/guitar/7611.png 4 +sketch/guitar/7612.png 4 +sketch/guitar/7613.png 4 +sketch/guitar/7614.png 4 +sketch/guitar/7615.png 4 +sketch/guitar/7616.png 4 +sketch/guitar/7617.png 4 +sketch/guitar/7618.png 4 +sketch/guitar/7619.png 4 +sketch/guitar/7620.png 4 +sketch/guitar/7621.png 4 +sketch/guitar/7622.png 4 +sketch/guitar/7623.png 4 +sketch/guitar/7624.png 4 +sketch/guitar/7625.png 4 +sketch/guitar/7626.png 4 +sketch/guitar/7627.png 4 +sketch/guitar/7628.png 4 +sketch/guitar/7629.png 4 +sketch/guitar/7630.png 4 +sketch/guitar/7631.png 4 +sketch/guitar/7632.png 4 +sketch/guitar/7633.png 4 +sketch/guitar/7634.png 4 +sketch/guitar/7635.png 4 +sketch/guitar/7636.png 4 +sketch/guitar/7637.png 4 +sketch/guitar/7638.png 4 +sketch/guitar/7639.png 4 +sketch/guitar/7640.png 4 +sketch/guitar/7641.png 4 +sketch/guitar/7642.png 4 +sketch/guitar/7643.png 4 +sketch/guitar/7644.png 4 +sketch/guitar/7645.png 4 +sketch/guitar/7646.png 4 +sketch/guitar/7647.png 4 +sketch/guitar/7648.png 4 +sketch/guitar/7649.png 4 +sketch/guitar/7650.png 4 +sketch/guitar/7651.png 4 +sketch/guitar/7652.png 4 +sketch/guitar/7653.png 4 +sketch/guitar/7654.png 4 +sketch/guitar/7655.png 4 +sketch/guitar/7656.png 4 +sketch/guitar/7657.png 4 +sketch/guitar/7658.png 4 +sketch/guitar/7659.png 4 +sketch/guitar/7660.png 4 +sketch/guitar/7661.png 4 +sketch/horse/n02374451_54-1.png 5 +sketch/horse/n02374451_54-2.png 5 +sketch/horse/n02374451_54-3.png 5 +sketch/horse/n02374451_54-4.png 5 +sketch/horse/n02374451_54-5.png 5 +sketch/horse/n02374451_54-6.png 5 +sketch/horse/n02374451_54-7.png 5 +sketch/horse/n02374451_54-8.png 5 +sketch/horse/n02374451_54-9.png 5 +sketch/horse/n02374451_54-10.png 5 +sketch/horse/n02374451_245-1.png 5 +sketch/horse/n02374451_245-2.png 5 +sketch/horse/n02374451_245-3.png 5 +sketch/horse/n02374451_245-4.png 5 +sketch/horse/n02374451_245-5.png 5 +sketch/horse/n02374451_245-6.png 5 +sketch/horse/n02374451_257-1.png 5 +sketch/horse/n02374451_257-2.png 5 +sketch/horse/n02374451_257-3.png 5 +sketch/horse/n02374451_257-4.png 5 +sketch/horse/n02374451_257-5.png 5 +sketch/horse/n02374451_257-6.png 5 +sketch/horse/n02374451_257-7.png 5 +sketch/horse/n02374451_262-1.png 5 +sketch/horse/n02374451_262-2.png 5 +sketch/horse/n02374451_262-3.png 5 +sketch/horse/n02374451_262-4.png 5 +sketch/horse/n02374451_262-5.png 5 +sketch/horse/n02374451_262-6.png 5 +sketch/horse/n02374451_262-7.png 5 +sketch/horse/n02374451_262-8.png 5 +sketch/horse/n02374451_262-9.png 5 +sketch/horse/n02374451_262-10.png 5 +sketch/horse/n02374451_262-11.png 5 +sketch/horse/n02374451_262-12.png 5 +sketch/horse/n02374451_276-1.png 5 +sketch/horse/n02374451_276-2.png 5 +sketch/horse/n02374451_276-3.png 5 +sketch/horse/n02374451_276-4.png 5 +sketch/horse/n02374451_276-5.png 5 +sketch/horse/n02374451_276-6.png 5 +sketch/horse/n02374451_276-7.png 5 +sketch/horse/n02374451_276-8.png 5 +sketch/horse/n02374451_276-9.png 5 +sketch/horse/n02374451_276-10.png 5 +sketch/horse/n02374451_388-2.png 5 +sketch/horse/n02374451_388-3.png 5 +sketch/horse/n02374451_388-4.png 5 +sketch/horse/n02374451_388-5.png 5 +sketch/horse/n02374451_388-6.png 5 +sketch/horse/n02374451_388-7.png 5 +sketch/horse/n02374451_388-8.png 5 +sketch/horse/n02374451_388-9.png 5 +sketch/horse/n02374451_388-10.png 5 +sketch/horse/n02374451_468-1.png 5 +sketch/horse/n02374451_468-2.png 5 +sketch/horse/n02374451_468-3.png 5 +sketch/horse/n02374451_468-4.png 5 +sketch/horse/n02374451_468-5.png 5 +sketch/horse/n02374451_468-6.png 5 +sketch/horse/n02374451_468-7.png 5 +sketch/horse/n02374451_468-8.png 5 +sketch/horse/n02374451_468-9.png 5 +sketch/horse/n02374451_468-10.png 5 +sketch/horse/n02374451_490-1.png 5 +sketch/horse/n02374451_490-2.png 5 +sketch/horse/n02374451_490-3.png 5 +sketch/horse/n02374451_490-4.png 5 +sketch/horse/n02374451_490-5.png 5 +sketch/horse/n02374451_490-6.png 5 +sketch/horse/n02374451_490-7.png 5 +sketch/horse/n02374451_503-1.png 5 +sketch/horse/n02374451_503-2.png 5 +sketch/horse/n02374451_503-3.png 5 +sketch/horse/n02374451_503-4.png 5 +sketch/horse/n02374451_503-5.png 5 +sketch/horse/n02374451_503-6.png 5 +sketch/horse/n02374451_557-1.png 5 +sketch/horse/n02374451_557-2.png 5 +sketch/horse/n02374451_557-3.png 5 +sketch/horse/n02374451_557-4.png 5 +sketch/horse/n02374451_557-5.png 5 +sketch/house/8801.png 6 +sketch/house/8802.png 6 +sketch/house/8803.png 6 +sketch/house/8804.png 6 +sketch/house/8805.png 6 +sketch/house/8806.png 6 +sketch/house/8807.png 6 +sketch/house/8808.png 6 +sketch/house/8809.png 6 +sketch/person/12081.png 7 +sketch/person/12082.png 7 +sketch/person/12083.png 7 +sketch/person/12084.png 7 +sketch/person/12085.png 7 +sketch/person/12086.png 7 +sketch/person/12087.png 7 +sketch/person/12088.png 7 +sketch/person/12089.png 7 +sketch/person/12090.png 7 +sketch/person/12091.png 7 +sketch/person/12092.png 7 +sketch/person/12093.png 7 +sketch/person/12094.png 7 +sketch/person/12095.png 7 +sketch/person/12096.png 7 +sketch/person/12097.png 7 diff --git a/domainlab/zdata/pacs_split/sketch_test_kfold.txt b/domainlab/zdata/pacs_split/sketch_test_kfold.txt new file mode 100644 index 000000000..c27970b06 --- /dev/null +++ b/domainlab/zdata/pacs_split/sketch_test_kfold.txt @@ -0,0 +1,3929 @@ +sketch/dog/n02103406_343-1.png 1 +sketch/dog/n02103406_343-2.png 1 +sketch/dog/n02103406_343-3.png 1 +sketch/dog/n02103406_343-4.png 1 +sketch/dog/n02103406_343-5.png 1 +sketch/dog/n02103406_343-6.png 1 +sketch/dog/n02103406_343-7.png 1 +sketch/dog/n02103406_343-8.png 1 +sketch/dog/n02103406_343-9.png 1 +sketch/dog/n02103406_346-1.png 1 +sketch/dog/n02103406_346-2.png 1 +sketch/dog/n02103406_346-3.png 1 +sketch/dog/n02103406_346-4.png 1 +sketch/dog/n02103406_346-5.png 1 +sketch/dog/n02103406_346-6.png 1 +sketch/dog/n02103406_346-7.png 1 +sketch/dog/n02103406_371-1.png 1 +sketch/dog/n02103406_371-2.png 1 +sketch/dog/n02103406_371-3.png 1 +sketch/dog/n02103406_371-4.png 1 +sketch/dog/n02103406_371-5.png 1 +sketch/dog/n02103406_371-6.png 1 +sketch/dog/n02103406_371-7.png 1 +sketch/dog/n02103406_371-8.png 1 +sketch/dog/n02103406_371-9.png 1 +sketch/dog/n02103406_371-10.png 1 +sketch/dog/n02103406_371-11.png 1 +sketch/dog/n02103406_651-1.png 1 +sketch/dog/n02103406_651-2.png 1 +sketch/dog/n02103406_651-3.png 1 +sketch/dog/n02103406_651-4.png 1 +sketch/dog/n02103406_651-5.png 1 +sketch/dog/n02103406_651-6.png 1 +sketch/dog/n02103406_651-7.png 1 +sketch/dog/n02103406_865-1.png 1 +sketch/dog/n02103406_865-2.png 1 +sketch/dog/n02103406_865-3.png 1 +sketch/dog/n02103406_865-4.png 1 +sketch/dog/n02103406_865-5.png 1 +sketch/dog/n02103406_865-6.png 1 +sketch/dog/n02103406_865-7.png 1 +sketch/dog/n02103406_865-8.png 1 +sketch/dog/n02103406_865-9.png 1 +sketch/dog/n02103406_865-10.png 1 +sketch/dog/n02103406_865-11.png 1 +sketch/dog/n02103406_936-1.png 1 +sketch/dog/n02103406_936-2.png 1 +sketch/dog/n02103406_936-3.png 1 +sketch/dog/n02103406_936-4.png 1 +sketch/dog/n02103406_936-5.png 1 +sketch/dog/n02103406_936-6.png 1 +sketch/dog/n02103406_936-7.png 1 +sketch/dog/n02103406_936-8.png 1 +sketch/dog/n02103406_936-9.png 1 +sketch/dog/n02103406_995-1.png 1 +sketch/dog/n02103406_995-2.png 1 +sketch/dog/n02103406_995-3.png 1 +sketch/dog/n02103406_995-4.png 1 +sketch/dog/n02103406_995-5.png 1 +sketch/dog/n02103406_995-6.png 1 +sketch/dog/n02103406_1011-1.png 1 +sketch/dog/n02103406_1011-2.png 1 +sketch/dog/n02103406_1011-3.png 1 +sketch/dog/n02103406_1011-4.png 1 +sketch/dog/n02103406_1011-5.png 1 +sketch/dog/n02103406_1138-1.png 1 +sketch/dog/n02103406_1138-2.png 1 +sketch/dog/n02103406_1138-3.png 1 +sketch/dog/n02103406_1138-4.png 1 +sketch/dog/n02103406_1138-5.png 1 +sketch/dog/n02103406_1138-6.png 1 +sketch/dog/n02103406_1138-7.png 1 +sketch/dog/n02103406_1138-8.png 1 +sketch/dog/n02103406_1170-1.png 1 +sketch/dog/n02103406_1170-2.png 1 +sketch/dog/n02103406_1170-3.png 1 +sketch/dog/n02103406_1170-4.png 1 +sketch/dog/n02103406_1170-5.png 1 +sketch/dog/n02103406_1170-6.png 1 +sketch/dog/n02103406_1247-1.png 1 +sketch/dog/n02103406_1247-2.png 1 +sketch/dog/n02103406_1247-3.png 1 +sketch/dog/n02103406_1247-4.png 1 +sketch/dog/n02103406_1247-5.png 1 +sketch/dog/n02103406_1247-6.png 1 +sketch/dog/n02103406_1247-7.png 1 +sketch/dog/n02103406_1599-1.png 1 +sketch/dog/n02103406_1599-2.png 1 +sketch/dog/n02103406_1599-3.png 1 +sketch/dog/n02103406_1599-4.png 1 +sketch/dog/n02103406_1599-5.png 1 +sketch/dog/n02103406_1754-1.png 1 +sketch/dog/n02103406_1754-2.png 1 +sketch/dog/n02103406_1754-3.png 1 +sketch/dog/n02103406_1754-4.png 1 +sketch/dog/n02103406_1754-5.png 1 +sketch/dog/n02103406_2209-1.png 1 +sketch/dog/n02103406_2209-2.png 1 +sketch/dog/n02103406_2209-3.png 1 +sketch/dog/n02103406_2209-4.png 1 +sketch/dog/n02103406_2209-5.png 1 +sketch/dog/n02103406_2209-6.png 1 +sketch/dog/n02103406_2209-7.png 1 +sketch/dog/n02103406_2209-8.png 1 +sketch/dog/n02103406_2706-1.png 1 +sketch/dog/n02103406_2706-2.png 1 +sketch/dog/n02103406_2706-3.png 1 +sketch/dog/n02103406_2706-4.png 1 +sketch/dog/n02103406_2706-5.png 1 +sketch/dog/n02103406_2706-6.png 1 +sketch/dog/n02103406_2706-7.png 1 +sketch/dog/n02103406_2706-8.png 1 +sketch/dog/n02103406_2706-9.png 1 +sketch/dog/n02103406_2954-1.png 1 +sketch/dog/n02103406_2954-2.png 1 +sketch/dog/n02103406_2954-3.png 1 +sketch/dog/n02103406_2954-4.png 1 +sketch/dog/n02103406_2954-5.png 1 +sketch/dog/n02103406_2954-6.png 1 +sketch/dog/n02103406_2976-1.png 1 +sketch/dog/n02103406_2976-2.png 1 +sketch/dog/n02103406_2976-3.png 1 +sketch/dog/n02103406_2976-4.png 1 +sketch/dog/n02103406_2976-5.png 1 +sketch/dog/n02103406_2976-6.png 1 +sketch/dog/n02103406_2976-7.png 1 +sketch/dog/n02103406_3056-1.png 1 +sketch/dog/n02103406_3056-2.png 1 +sketch/dog/n02103406_3056-3.png 1 +sketch/dog/n02103406_3056-4.png 1 +sketch/dog/n02103406_3056-5.png 1 +sketch/dog/n02103406_3108-1.png 1 +sketch/dog/n02103406_3108-2.png 1 +sketch/dog/n02103406_3108-3.png 1 +sketch/dog/n02103406_3108-4.png 1 +sketch/dog/n02103406_3108-5.png 1 +sketch/dog/n02103406_3108-6.png 1 +sketch/dog/n02103406_3132-1.png 1 +sketch/dog/n02103406_3132-2.png 1 +sketch/dog/n02103406_3132-3.png 1 +sketch/dog/n02103406_3132-4.png 1 +sketch/dog/n02103406_3132-5.png 1 +sketch/dog/n02103406_3132-6.png 1 +sketch/dog/n02103406_3132-7.png 1 +sketch/dog/n02103406_3255-1.png 1 +sketch/dog/n02103406_3255-2.png 1 +sketch/dog/n02103406_3255-3.png 1 +sketch/dog/n02103406_3255-4.png 1 +sketch/dog/n02103406_3255-5.png 1 +sketch/dog/n02103406_3255-6.png 1 +sketch/dog/n02103406_3255-7.png 1 +sketch/dog/n02103406_3255-8.png 1 +sketch/dog/n02103406_3255-9.png 1 +sketch/dog/n02103406_3255-10.png 1 +sketch/dog/n02103406_3255-11.png 1 +sketch/dog/n02103406_3299-1.png 1 +sketch/dog/n02103406_3299-2.png 1 +sketch/dog/n02103406_3299-3.png 1 +sketch/dog/n02103406_3299-4.png 1 +sketch/dog/n02103406_3299-5.png 1 +sketch/dog/n02103406_3299-6.png 1 +sketch/dog/n02103406_3299-7.png 1 +sketch/dog/n02103406_3299-8.png 1 +sketch/dog/n02103406_3299-9.png 1 +sketch/dog/n02103406_3326-1.png 1 +sketch/dog/n02103406_3326-2.png 1 +sketch/dog/n02103406_3326-3.png 1 +sketch/dog/n02103406_3326-4.png 1 +sketch/dog/n02103406_3326-5.png 1 +sketch/dog/n02103406_3326-6.png 1 +sketch/dog/n02103406_3326-7.png 1 +sketch/dog/n02103406_3326-8.png 1 +sketch/dog/n02103406_3326-9.png 1 +sketch/dog/n02103406_3326-10.png 1 +sketch/dog/n02103406_3326-11.png 1 +sketch/dog/n02103406_3326-12.png 1 +sketch/dog/n02103406_3326-13.png 1 +sketch/dog/n02103406_3401-1.png 1 +sketch/dog/n02103406_3401-2.png 1 +sketch/dog/n02103406_3401-3.png 1 +sketch/dog/n02103406_3401-4.png 1 +sketch/dog/n02103406_3401-5.png 1 +sketch/dog/n02103406_3401-6.png 1 +sketch/dog/n02103406_3538-1.png 1 +sketch/dog/n02103406_3538-2.png 1 +sketch/dog/n02103406_3538-3.png 1 +sketch/dog/n02103406_3538-4.png 1 +sketch/dog/n02103406_3538-5.png 1 +sketch/dog/n02103406_3538-6.png 1 +sketch/dog/n02103406_3538-7.png 1 +sketch/dog/n02103406_3743-1.png 1 +sketch/dog/n02103406_3743-2.png 1 +sketch/dog/n02103406_3743-3.png 1 +sketch/dog/n02103406_3743-4.png 1 +sketch/dog/n02103406_3743-5.png 1 +sketch/dog/n02103406_3743-6.png 1 +sketch/dog/n02103406_3743-7.png 1 +sketch/dog/n02103406_3743-8.png 1 +sketch/dog/n02103406_3743-9.png 1 +sketch/dog/n02103406_3743-10.png 1 +sketch/dog/n02103406_3750-1.png 1 +sketch/dog/n02103406_3750-2.png 1 +sketch/dog/n02103406_3750-3.png 1 +sketch/dog/n02103406_3750-4.png 1 +sketch/dog/n02103406_3750-5.png 1 +sketch/dog/n02103406_3750-6.png 1 +sketch/dog/n02103406_3964-1.png 1 +sketch/dog/n02103406_3964-2.png 1 +sketch/dog/n02103406_3964-3.png 1 +sketch/dog/n02103406_3964-4.png 1 +sketch/dog/n02103406_3964-5.png 1 +sketch/dog/n02103406_4068-1.png 1 +sketch/dog/n02103406_4068-2.png 1 +sketch/dog/n02103406_4068-3.png 1 +sketch/dog/n02103406_4068-4.png 1 +sketch/dog/n02103406_4068-5.png 1 +sketch/dog/n02103406_4068-6.png 1 +sketch/dog/n02103406_4068-7.png 1 +sketch/dog/n02103406_4068-8.png 1 +sketch/dog/n02103406_4068-9.png 1 +sketch/dog/n02103406_4068-10.png 1 +sketch/dog/n02103406_4068-11.png 1 +sketch/dog/n02103406_4068-12.png 1 +sketch/dog/n02103406_4582-1.png 1 +sketch/dog/n02103406_4582-2.png 1 +sketch/dog/n02103406_4582-3.png 1 +sketch/dog/n02103406_4582-4.png 1 +sketch/dog/n02103406_4582-5.png 1 +sketch/dog/n02103406_4849-1.png 1 +sketch/dog/n02103406_4849-2.png 1 +sketch/dog/n02103406_4849-3.png 1 +sketch/dog/n02103406_4849-4.png 1 +sketch/dog/n02103406_4849-5.png 1 +sketch/dog/n02103406_4849-6.png 1 +sketch/dog/n02103406_4849-7.png 1 +sketch/dog/n02103406_4849-8.png 1 +sketch/dog/n02103406_4849-9.png 1 +sketch/dog/n02103406_4916-1.png 1 +sketch/dog/n02103406_4916-2.png 1 +sketch/dog/n02103406_4916-3.png 1 +sketch/dog/n02103406_4916-4.png 1 +sketch/dog/n02103406_4916-5.png 1 +sketch/dog/n02103406_5035-1.png 1 +sketch/dog/n02103406_5035-2.png 1 +sketch/dog/n02103406_5035-3.png 1 +sketch/dog/n02103406_5035-4.png 1 +sketch/dog/n02103406_5035-5.png 1 +sketch/dog/n02103406_5035-6.png 1 +sketch/dog/n02103406_5216-1.png 1 +sketch/dog/n02103406_5216-2.png 1 +sketch/dog/n02103406_5216-3.png 1 +sketch/dog/n02103406_5216-4.png 1 +sketch/dog/n02103406_5216-5.png 1 +sketch/dog/n02103406_5224-1.png 1 +sketch/dog/n02103406_5224-2.png 1 +sketch/dog/n02103406_5224-3.png 1 +sketch/dog/n02103406_5224-4.png 1 +sketch/dog/n02103406_5224-5.png 1 +sketch/dog/n02103406_5224-6.png 1 +sketch/dog/n02103406_5456-1.png 1 +sketch/dog/n02103406_5456-2.png 1 +sketch/dog/n02103406_5456-3.png 1 +sketch/dog/n02103406_5456-4.png 1 +sketch/dog/n02103406_5456-5.png 1 +sketch/dog/n02103406_5456-6.png 1 +sketch/dog/n02103406_5456-7.png 1 +sketch/dog/n02103406_5456-8.png 1 +sketch/dog/n02103406_5456-9.png 1 +sketch/dog/n02103406_5505-1.png 1 +sketch/dog/n02103406_5505-2.png 1 +sketch/dog/n02103406_5505-3.png 1 +sketch/dog/n02103406_5505-4.png 1 +sketch/dog/n02103406_5505-5.png 1 +sketch/dog/n02103406_5505-6.png 1 +sketch/dog/n02103406_5563-1.png 1 +sketch/dog/n02103406_5563-2.png 1 +sketch/dog/n02103406_5563-3.png 1 +sketch/dog/n02103406_5563-4.png 1 +sketch/dog/n02103406_5563-5.png 1 +sketch/dog/n02103406_5563-6.png 1 +sketch/dog/n02103406_5563-7.png 1 +sketch/dog/n02103406_5601-1.png 1 +sketch/dog/n02103406_5601-2.png 1 +sketch/dog/n02103406_5601-3.png 1 +sketch/dog/n02103406_5601-4.png 1 +sketch/dog/n02103406_5601-5.png 1 +sketch/dog/n02103406_5601-6.png 1 +sketch/dog/n02103406_6274-1.png 1 +sketch/dog/n02103406_6274-2.png 1 +sketch/dog/n02103406_6274-3.png 1 +sketch/dog/n02103406_6274-4.png 1 +sketch/dog/n02103406_6274-5.png 1 +sketch/dog/n02103406_6461-1.png 1 +sketch/dog/n02103406_6461-2.png 1 +sketch/dog/n02103406_6461-3.png 1 +sketch/dog/n02103406_6461-4.png 1 +sketch/dog/n02103406_6461-5.png 1 +sketch/dog/n02103406_6461-6.png 1 +sketch/dog/n02103406_6461-7.png 1 +sketch/dog/n02103406_6530-1.png 1 +sketch/dog/n02103406_6530-2.png 1 +sketch/dog/n02103406_6530-3.png 1 +sketch/dog/n02103406_6530-4.png 1 +sketch/dog/n02103406_6530-5.png 1 +sketch/dog/n02103406_6530-6.png 1 +sketch/dog/n02103406_6530-7.png 1 +sketch/dog/n02103406_6688-1.png 1 +sketch/dog/n02103406_6688-2.png 1 +sketch/dog/n02103406_6688-3.png 1 +sketch/dog/n02103406_6688-4.png 1 +sketch/dog/n02103406_6688-5.png 1 +sketch/dog/n02103406_6688-6.png 1 +sketch/dog/n02103406_6688-7.png 1 +sketch/dog/n02103406_6688-8.png 1 +sketch/dog/n02103406_6688-9.png 1 +sketch/dog/n02103406_6852-1.png 1 +sketch/dog/n02103406_6852-2.png 1 +sketch/dog/n02103406_6852-3.png 1 +sketch/dog/n02103406_6852-4.png 1 +sketch/dog/n02103406_6852-5.png 1 +sketch/dog/n02103406_6852-6.png 1 +sketch/dog/n02103406_6852-7.png 1 +sketch/dog/n02103406_6852-8.png 1 +sketch/dog/n02103406_6852-9.png 1 +sketch/dog/n02103406_6857-1.png 1 +sketch/dog/n02103406_6857-2.png 1 +sketch/dog/n02103406_6857-3.png 1 +sketch/dog/n02103406_6857-4.png 1 +sketch/dog/n02103406_6857-5.png 1 +sketch/dog/n02103406_6857-6.png 1 +sketch/dog/n02103406_6857-7.png 1 +sketch/dog/n02103406_6857-8.png 1 +sketch/dog/n02103406_7201-1.png 1 +sketch/dog/n02103406_7201-2.png 1 +sketch/dog/n02103406_7201-3.png 1 +sketch/dog/n02103406_7201-4.png 1 +sketch/dog/n02103406_7201-5.png 1 +sketch/dog/n02103406_7201-6.png 1 +sketch/dog/n02103406_7368-1.png 1 +sketch/dog/n02103406_7368-2.png 1 +sketch/dog/n02103406_7368-3.png 1 +sketch/dog/n02103406_7368-4.png 1 +sketch/dog/n02103406_7368-5.png 1 +sketch/dog/n02103406_7368-6.png 1 +sketch/dog/n02103406_7368-7.png 1 +sketch/dog/n02103406_7368-8.png 1 +sketch/dog/n02103406_7368-9.png 1 +sketch/dog/n02103406_7368-10.png 1 +sketch/dog/n02103406_7521-1.png 1 +sketch/dog/n02103406_7521-2.png 1 +sketch/dog/n02103406_7521-3.png 1 +sketch/dog/n02103406_7521-4.png 1 +sketch/dog/n02103406_7521-5.png 1 +sketch/dog/n02103406_7521-6.png 1 +sketch/dog/n02103406_7521-7.png 1 +sketch/dog/n02103406_7521-8.png 1 +sketch/dog/n02103406_7708-1.png 1 +sketch/dog/n02103406_7708-2.png 1 +sketch/dog/n02103406_7708-3.png 1 +sketch/dog/n02103406_7708-4.png 1 +sketch/dog/n02103406_7708-5.png 1 +sketch/dog/n02103406_7708-6.png 1 +sketch/dog/n02103406_7708-7.png 1 +sketch/dog/n02103406_7708-8.png 1 +sketch/dog/n02103406_7708-9.png 1 +sketch/dog/n02103406_7708-10.png 1 +sketch/dog/n02103406_8004-1.png 1 +sketch/dog/n02103406_8004-2.png 1 +sketch/dog/n02103406_8004-3.png 1 +sketch/dog/n02103406_8004-4.png 1 +sketch/dog/n02103406_8004-5.png 1 +sketch/dog/n02103406_8004-6.png 1 +sketch/dog/n02103406_8004-7.png 1 +sketch/dog/n02103406_8004-8.png 1 +sketch/dog/n02103406_8004-9.png 1 +sketch/dog/n02103406_8280-1.png 1 +sketch/dog/n02103406_8280-2.png 1 +sketch/dog/n02103406_8280-3.png 1 +sketch/dog/n02103406_8280-4.png 1 +sketch/dog/n02103406_8280-5.png 1 +sketch/dog/n02103406_8280-6.png 1 +sketch/dog/n02103406_8362-1.png 1 +sketch/dog/n02103406_8362-2.png 1 +sketch/dog/n02103406_8362-3.png 1 +sketch/dog/n02103406_8362-4.png 1 +sketch/dog/n02103406_8362-5.png 1 +sketch/dog/n02103406_8362-6.png 1 +sketch/dog/n02103406_8362-7.png 1 +sketch/dog/n02103406_8362-8.png 1 +sketch/dog/n02103406_8362-9.png 1 +sketch/dog/n02103406_8362-10.png 1 +sketch/dog/n02103406_8421-1.png 1 +sketch/dog/n02103406_8421-2.png 1 +sketch/dog/n02103406_8421-3.png 1 +sketch/dog/n02103406_8421-4.png 1 +sketch/dog/n02103406_8421-5.png 1 +sketch/dog/n02103406_8421-6.png 1 +sketch/dog/n02103406_13049-1.png 1 +sketch/dog/n02103406_13049-2.png 1 +sketch/dog/n02103406_13049-3.png 1 +sketch/dog/n02103406_13049-4.png 1 +sketch/dog/n02103406_13049-5.png 1 +sketch/dog/n02103406_13049-6.png 1 +sketch/dog/n02106662_466-1.png 1 +sketch/dog/n02106662_466-2.png 1 +sketch/dog/n02106662_466-3.png 1 +sketch/dog/n02106662_466-4.png 1 +sketch/dog/n02106662_466-5.png 1 +sketch/dog/n02106662_466-6.png 1 +sketch/dog/n02106662_466-7.png 1 +sketch/dog/n02106662_928-1.png 1 +sketch/dog/n02106662_928-2.png 1 +sketch/dog/n02106662_928-3.png 1 +sketch/dog/n02106662_928-4.png 1 +sketch/dog/n02106662_928-5.png 1 +sketch/dog/n02106662_928-6.png 1 +sketch/dog/n02106662_928-7.png 1 +sketch/dog/n02106662_928-8.png 1 +sketch/dog/n02106662_928-9.png 1 +sketch/dog/n02106662_928-10.png 1 +sketch/dog/n02106662_928-11.png 1 +sketch/dog/n02106662_1874-1.png 1 +sketch/dog/n02106662_1874-2.png 1 +sketch/dog/n02106662_1874-3.png 1 +sketch/dog/n02106662_1874-4.png 1 +sketch/dog/n02106662_1874-5.png 1 +sketch/dog/n02106662_1922-1.png 1 +sketch/dog/n02106662_1922-2.png 1 +sketch/dog/n02106662_1922-3.png 1 +sketch/dog/n02106662_1922-4.png 1 +sketch/dog/n02106662_1922-5.png 1 +sketch/dog/n02106662_2101-1.png 1 +sketch/dog/n02106662_2101-2.png 1 +sketch/dog/n02106662_2101-3.png 1 +sketch/dog/n02106662_2101-4.png 1 +sketch/dog/n02106662_2101-5.png 1 +sketch/dog/n02106662_2101-6.png 1 +sketch/dog/n02106662_2101-7.png 1 +sketch/dog/n02106662_2101-8.png 1 +sketch/dog/n02106662_2101-9.png 1 +sketch/dog/n02106662_2157-1.png 1 +sketch/dog/n02106662_2157-2.png 1 +sketch/dog/n02106662_2157-3.png 1 +sketch/dog/n02106662_2157-4.png 1 +sketch/dog/n02106662_2157-5.png 1 +sketch/dog/n02106662_2157-6.png 1 +sketch/dog/n02106662_2377-1.png 1 +sketch/dog/n02106662_2377-2.png 1 +sketch/dog/n02106662_2377-3.png 1 +sketch/dog/n02106662_2377-4.png 1 +sketch/dog/n02106662_2377-5.png 1 +sketch/dog/n02106662_2377-6.png 1 +sketch/dog/n02106662_2740-1.png 1 +sketch/dog/n02106662_2740-2.png 1 +sketch/dog/n02106662_2740-3.png 1 +sketch/dog/n02106662_2740-4.png 1 +sketch/dog/n02106662_2740-5.png 1 +sketch/dog/n02106662_5001-1.png 1 +sketch/dog/n02106662_5001-2.png 1 +sketch/dog/n02106662_5001-3.png 1 +sketch/dog/n02106662_5001-4.png 1 +sketch/dog/n02106662_5001-5.png 1 +sketch/dog/n02106662_5001-6.png 1 +sketch/dog/n02106662_5001-7.png 1 +sketch/dog/n02106662_7885-1.png 1 +sketch/dog/n02106662_7885-2.png 1 +sketch/dog/n02106662_7885-3.png 1 +sketch/dog/n02106662_7885-4.png 1 +sketch/dog/n02106662_7885-5.png 1 +sketch/dog/n02106662_7960-1.png 1 +sketch/dog/n02106662_7960-2.png 1 +sketch/dog/n02106662_7960-3.png 1 +sketch/dog/n02106662_7960-4.png 1 +sketch/dog/n02106662_7960-5.png 1 +sketch/dog/n02106662_7960-6.png 1 +sketch/dog/n02106662_8511-1.png 1 +sketch/dog/n02106662_8511-2.png 1 +sketch/dog/n02106662_8511-3.png 1 +sketch/dog/n02106662_8511-4.png 1 +sketch/dog/n02106662_8511-5.png 1 +sketch/dog/n02106662_8511-6.png 1 +sketch/dog/n02106662_8870-1.png 1 +sketch/dog/n02106662_8870-2.png 1 +sketch/dog/n02106662_8870-3.png 1 +sketch/dog/n02106662_8870-4.png 1 +sketch/dog/n02106662_8870-5.png 1 +sketch/dog/n02106662_8870-6.png 1 +sketch/dog/n02106662_8870-7.png 1 +sketch/dog/n02106662_10406-1.png 1 +sketch/dog/n02106662_10406-2.png 1 +sketch/dog/n02106662_10406-3.png 1 +sketch/dog/n02106662_10406-4.png 1 +sketch/dog/n02106662_10406-5.png 1 +sketch/dog/n02106662_10406-6.png 1 +sketch/dog/n02106662_11133-1.png 1 +sketch/dog/n02106662_11133-2.png 1 +sketch/dog/n02106662_11133-3.png 1 +sketch/dog/n02106662_11133-4.png 1 +sketch/dog/n02106662_11133-5.png 1 +sketch/dog/n02106662_13178-1.png 1 +sketch/dog/n02106662_13178-2.png 1 +sketch/dog/n02106662_13178-3.png 1 +sketch/dog/n02106662_13178-4.png 1 +sketch/dog/n02106662_13178-5.png 1 +sketch/dog/n02106662_13912-1.png 1 +sketch/dog/n02106662_13912-2.png 1 +sketch/dog/n02106662_13912-3.png 1 +sketch/dog/n02106662_13912-4.png 1 +sketch/dog/n02106662_13912-5.png 1 +sketch/dog/n02106662_15858-1.png 1 +sketch/dog/n02106662_15858-2.png 1 +sketch/dog/n02106662_15858-3.png 1 +sketch/dog/n02106662_15858-4.png 1 +sketch/dog/n02106662_15858-5.png 1 +sketch/dog/n02106662_15858-6.png 1 +sketch/dog/n02106662_18402-1.png 1 +sketch/dog/n02106662_18402-2.png 1 +sketch/dog/n02106662_18402-3.png 1 +sketch/dog/n02106662_18402-4.png 1 +sketch/dog/n02106662_18402-5.png 1 +sketch/dog/n02106662_18405-1.png 1 +sketch/dog/n02106662_18405-2.png 1 +sketch/dog/n02106662_18405-3.png 1 +sketch/dog/n02106662_18405-4.png 1 +sketch/dog/n02106662_18405-5.png 1 +sketch/dog/n02106662_18922-1.png 1 +sketch/dog/n02106662_18922-2.png 1 +sketch/dog/n02106662_18922-3.png 1 +sketch/dog/n02106662_18922-4.png 1 +sketch/dog/n02106662_18922-5.png 1 +sketch/dog/n02106662_18922-6.png 1 +sketch/dog/n02106662_18922-7.png 1 +sketch/dog/n02106662_18922-8.png 1 +sketch/dog/n02106662_18922-9.png 1 +sketch/dog/n02106662_18922-10.png 1 +sketch/dog/n02106662_18922-11.png 1 +sketch/dog/n02106662_18953-1.png 1 +sketch/dog/n02106662_18953-2.png 1 +sketch/dog/n02106662_18953-3.png 1 +sketch/dog/n02106662_18953-4.png 1 +sketch/dog/n02106662_18953-5.png 1 +sketch/dog/n02106662_18953-6.png 1 +sketch/dog/n02106662_18953-7.png 1 +sketch/dog/n02106662_24019-1.png 1 +sketch/dog/n02106662_24019-2.png 1 +sketch/dog/n02106662_24019-3.png 1 +sketch/dog/n02106662_24019-4.png 1 +sketch/dog/n02106662_24019-5.png 1 +sketch/dog/n02106662_24019-6.png 1 +sketch/dog/n02106662_24019-7.png 1 +sketch/dog/n02106662_24019-8.png 1 +sketch/dog/n02106662_24577-1.png 1 +sketch/dog/n02106662_24577-2.png 1 +sketch/dog/n02106662_24577-3.png 1 +sketch/dog/n02106662_24577-4.png 1 +sketch/dog/n02106662_24577-5.png 1 +sketch/dog/n02106662_24786-1.png 1 +sketch/dog/n02106662_24786-2.png 1 +sketch/dog/n02106662_24786-3.png 1 +sketch/dog/n02106662_24786-4.png 1 +sketch/dog/n02106662_24786-5.png 1 +sketch/dog/n02106662_24786-6.png 1 +sketch/dog/n02106662_24786-7.png 1 +sketch/dog/n02106662_25917-1.png 1 +sketch/dog/n02106662_25917-2.png 1 +sketch/dog/n02106662_25917-3.png 1 +sketch/dog/n02106662_25917-4.png 1 +sketch/dog/n02106662_25917-5.png 1 +sketch/dog/n02106662_25917-6.png 1 +sketch/dog/n02106662_25917-7.png 1 +sketch/dog/n02106662_26549-1.png 1 +sketch/dog/n02106662_26549-2.png 1 +sketch/dog/n02106662_26549-3.png 1 +sketch/dog/n02106662_26549-4.png 1 +sketch/dog/n02106662_26549-5.png 1 +sketch/dog/n02106662_26549-6.png 1 +sketch/dog/n02106662_27393-1.png 1 +sketch/dog/n02106662_27393-2.png 1 +sketch/dog/n02106662_27393-3.png 1 +sketch/dog/n02106662_27393-4.png 1 +sketch/dog/n02106662_27393-5.png 1 +sketch/dog/n02109525_704-1.png 1 +sketch/dog/n02109525_704-2.png 1 +sketch/dog/n02109525_704-3.png 1 +sketch/dog/n02109525_704-4.png 1 +sketch/dog/n02109525_704-5.png 1 +sketch/dog/n02109525_704-6.png 1 +sketch/dog/n02109525_1893-1.png 1 +sketch/dog/n02109525_1893-2.png 1 +sketch/dog/n02109525_1893-3.png 1 +sketch/dog/n02109525_1893-4.png 1 +sketch/dog/n02109525_1893-5.png 1 +sketch/dog/n02109525_1893-6.png 1 +sketch/dog/n02109525_1893-7.png 1 +sketch/dog/n02109525_3202-1.png 1 +sketch/dog/n02109525_3202-2.png 1 +sketch/dog/n02109525_3202-3.png 1 +sketch/dog/n02109525_3202-4.png 1 +sketch/dog/n02109525_3202-5.png 1 +sketch/dog/n02109525_3202-6.png 1 +sketch/dog/n02109525_3782-1.png 1 +sketch/dog/n02109525_3782-2.png 1 +sketch/dog/n02109525_3782-3.png 1 +sketch/dog/n02109525_3782-4.png 1 +sketch/dog/n02109525_3782-5.png 1 +sketch/dog/n02109525_3782-6.png 1 +sketch/dog/n02109525_3782-7.png 1 +sketch/dog/n02109525_3782-8.png 1 +sketch/dog/n02109525_3782-9.png 1 +sketch/dog/n02109525_3782-10.png 1 +sketch/dog/n02109525_5013-1.png 1 +sketch/dog/n02109525_5013-2.png 1 +sketch/dog/n02109525_5013-3.png 1 +sketch/dog/n02109525_5013-4.png 1 +sketch/dog/n02109525_5013-5.png 1 +sketch/dog/n02109525_5013-6.png 1 +sketch/dog/n02109525_5583-1.png 1 +sketch/dog/n02109525_5583-2.png 1 +sketch/dog/n02109525_5583-3.png 1 +sketch/dog/n02109525_5583-4.png 1 +sketch/dog/n02109525_5583-5.png 1 +sketch/dog/n02109525_5583-6.png 1 +sketch/dog/n02109525_5583-7.png 1 +sketch/dog/n02109525_5966-1.png 1 +sketch/dog/n02109525_5966-2.png 1 +sketch/dog/n02109525_5966-3.png 1 +sketch/dog/n02109525_5966-4.png 1 +sketch/dog/n02109525_5966-5.png 1 +sketch/dog/n02109525_6693-1.png 1 +sketch/dog/n02109525_6693-2.png 1 +sketch/dog/n02109525_6693-3.png 1 +sketch/dog/n02109525_6693-4.png 1 +sketch/dog/n02109525_6693-5.png 1 +sketch/dog/n02109525_7874-1.png 1 +sketch/dog/n02109525_7874-2.png 1 +sketch/dog/n02109525_7874-3.png 1 +sketch/dog/n02109525_7874-4.png 1 +sketch/dog/n02109525_7874-5.png 1 +sketch/dog/n02109525_7874-6.png 1 +sketch/dog/n02109525_8211-1.png 1 +sketch/dog/n02109525_8211-2.png 1 +sketch/dog/n02109525_8211-3.png 1 +sketch/dog/n02109525_8211-4.png 1 +sketch/dog/n02109525_8211-5.png 1 +sketch/dog/n02109525_8457-1.png 1 +sketch/dog/n02109525_8457-2.png 1 +sketch/dog/n02109525_8457-3.png 1 +sketch/dog/n02109525_8457-4.png 1 +sketch/dog/n02109525_8457-5.png 1 +sketch/dog/n02109525_9037-1.png 1 +sketch/dog/n02109525_9037-2.png 1 +sketch/dog/n02109525_9037-3.png 1 +sketch/dog/n02109525_9037-4.png 1 +sketch/dog/n02109525_9037-5.png 1 +sketch/dog/n02109525_9037-6.png 1 +sketch/dog/n02109525_9037-7.png 1 +sketch/dog/n02109525_10297-1.png 1 +sketch/dog/n02109525_10297-2.png 1 +sketch/dog/n02109525_10297-3.png 1 +sketch/dog/n02109525_10297-4.png 1 +sketch/dog/n02109525_10297-5.png 1 +sketch/dog/n02109525_11444-1.png 1 +sketch/dog/n02109525_11444-2.png 1 +sketch/dog/n02109525_11444-3.png 1 +sketch/dog/n02109525_11444-4.png 1 +sketch/dog/n02109525_11444-5.png 1 +sketch/dog/n02109525_12875-1.png 1 +sketch/dog/n02109525_12875-2.png 1 +sketch/dog/n02109525_12875-3.png 1 +sketch/dog/n02109525_12875-4.png 1 +sketch/dog/n02109525_12875-5.png 1 +sketch/dog/n02109525_12875-6.png 1 +sketch/dog/n02109525_13700-1.png 1 +sketch/dog/n02109525_13700-2.png 1 +sketch/dog/n02109525_13700-3.png 1 +sketch/dog/n02109525_13700-4.png 1 +sketch/dog/n02109525_13700-5.png 1 +sketch/dog/n02109525_16346-1.png 1 +sketch/dog/n02109525_16346-2.png 1 +sketch/dog/n02109525_16346-3.png 1 +sketch/dog/n02109525_16346-4.png 1 +sketch/dog/n02109525_16346-5.png 1 +sketch/dog/n02109525_16346-6.png 1 +sketch/dog/n02109525_16346-7.png 1 +sketch/dog/n02109525_16346-8.png 1 +sketch/dog/n02109525_18347-1.png 1 +sketch/dog/n02109525_18347-2.png 1 +sketch/dog/n02109525_18347-3.png 1 +sketch/dog/n02109525_18347-4.png 1 +sketch/dog/n02109525_18347-5.png 1 +sketch/dog/n02109525_18347-6.png 1 +sketch/dog/n02109525_18347-7.png 1 +sketch/dog/5281.png 1 +sketch/dog/5282.png 1 +sketch/dog/5283.png 1 +sketch/dog/5284.png 1 +sketch/dog/5285.png 1 +sketch/dog/5286.png 1 +sketch/dog/5287.png 1 +sketch/dog/5288.png 1 +sketch/dog/5289.png 1 +sketch/dog/5290.png 1 +sketch/dog/5291.png 1 +sketch/dog/5292.png 1 +sketch/dog/5293.png 1 +sketch/dog/5294.png 1 +sketch/dog/5295.png 1 +sketch/dog/5296.png 1 +sketch/dog/5297.png 1 +sketch/dog/5298.png 1 +sketch/dog/5299.png 1 +sketch/dog/5300.png 1 +sketch/dog/5301.png 1 +sketch/dog/5302.png 1 +sketch/dog/5303.png 1 +sketch/dog/5304.png 1 +sketch/dog/5305.png 1 +sketch/dog/5306.png 1 +sketch/dog/5307.png 1 +sketch/dog/5308.png 1 +sketch/dog/5309.png 1 +sketch/dog/5310.png 1 +sketch/dog/5311.png 1 +sketch/dog/5312.png 1 +sketch/dog/5313.png 1 +sketch/dog/5314.png 1 +sketch/dog/5315.png 1 +sketch/dog/5316.png 1 +sketch/dog/5317.png 1 +sketch/dog/5318.png 1 +sketch/dog/5319.png 1 +sketch/dog/5320.png 1 +sketch/dog/5321.png 1 +sketch/dog/5322.png 1 +sketch/dog/5323.png 1 +sketch/dog/5324.png 1 +sketch/dog/5325.png 1 +sketch/dog/5326.png 1 +sketch/dog/5327.png 1 +sketch/dog/5328.png 1 +sketch/dog/5329.png 1 +sketch/dog/5330.png 1 +sketch/dog/5331.png 1 +sketch/dog/5332.png 1 +sketch/dog/5333.png 1 +sketch/dog/5334.png 1 +sketch/dog/5335.png 1 +sketch/dog/5336.png 1 +sketch/dog/5337.png 1 +sketch/dog/5338.png 1 +sketch/dog/5339.png 1 +sketch/dog/5340.png 1 +sketch/dog/5341.png 1 +sketch/dog/5342.png 1 +sketch/dog/5343.png 1 +sketch/dog/5344.png 1 +sketch/dog/5345.png 1 +sketch/dog/5346.png 1 +sketch/dog/5347.png 1 +sketch/dog/5348.png 1 +sketch/dog/5349.png 1 +sketch/dog/5350.png 1 +sketch/dog/5351.png 1 +sketch/dog/5352.png 1 +sketch/dog/5353.png 1 +sketch/dog/5354.png 1 +sketch/dog/5355.png 1 +sketch/dog/5356.png 1 +sketch/dog/5357.png 1 +sketch/dog/5358.png 1 +sketch/dog/5359.png 1 +sketch/dog/5360.png 1 +sketch/elephant/n02503517_79-1.png 2 +sketch/elephant/n02503517_79-2.png 2 +sketch/elephant/n02503517_79-3.png 2 +sketch/elephant/n02503517_79-4.png 2 +sketch/elephant/n02503517_79-5.png 2 +sketch/elephant/n02503517_86-1.png 2 +sketch/elephant/n02503517_86-2.png 2 +sketch/elephant/n02503517_86-3.png 2 +sketch/elephant/n02503517_86-4.png 2 +sketch/elephant/n02503517_86-5.png 2 +sketch/elephant/n02503517_86-6.png 2 +sketch/elephant/n02503517_184-1.png 2 +sketch/elephant/n02503517_184-2.png 2 +sketch/elephant/n02503517_184-3.png 2 +sketch/elephant/n02503517_184-4.png 2 +sketch/elephant/n02503517_184-5.png 2 +sketch/elephant/n02503517_184-6.png 2 +sketch/elephant/n02503517_184-7.png 2 +sketch/elephant/n02503517_184-8.png 2 +sketch/elephant/n02503517_184-9.png 2 +sketch/elephant/n02503517_194-1.png 2 +sketch/elephant/n02503517_194-2.png 2 +sketch/elephant/n02503517_194-3.png 2 +sketch/elephant/n02503517_194-4.png 2 +sketch/elephant/n02503517_194-5.png 2 +sketch/elephant/n02503517_194-6.png 2 +sketch/elephant/n02503517_311-1.png 2 +sketch/elephant/n02503517_311-2.png 2 +sketch/elephant/n02503517_311-3.png 2 +sketch/elephant/n02503517_311-4.png 2 +sketch/elephant/n02503517_311-5.png 2 +sketch/elephant/n02503517_311-6.png 2 +sketch/elephant/n02503517_564-1.png 2 +sketch/elephant/n02503517_564-2.png 2 +sketch/elephant/n02503517_564-3.png 2 +sketch/elephant/n02503517_564-4.png 2 +sketch/elephant/n02503517_564-5.png 2 +sketch/elephant/n02503517_753-1.png 2 +sketch/elephant/n02503517_753-2.png 2 +sketch/elephant/n02503517_753-3.png 2 +sketch/elephant/n02503517_753-4.png 2 +sketch/elephant/n02503517_753-5.png 2 +sketch/elephant/n02503517_753-6.png 2 +sketch/elephant/n02503517_759-1.png 2 +sketch/elephant/n02503517_759-2.png 2 +sketch/elephant/n02503517_759-3.png 2 +sketch/elephant/n02503517_759-4.png 2 +sketch/elephant/n02503517_759-5.png 2 +sketch/elephant/n02503517_759-6.png 2 +sketch/elephant/n02503517_759-7.png 2 +sketch/elephant/n02503517_759-8.png 2 +sketch/elephant/n02503517_792-1.png 2 +sketch/elephant/n02503517_792-2.png 2 +sketch/elephant/n02503517_792-3.png 2 +sketch/elephant/n02503517_792-4.png 2 +sketch/elephant/n02503517_792-5.png 2 +sketch/elephant/n02503517_1292-1.png 2 +sketch/elephant/n02503517_1292-2.png 2 +sketch/elephant/n02503517_1292-3.png 2 +sketch/elephant/n02503517_1292-4.png 2 +sketch/elephant/n02503517_1292-5.png 2 +sketch/elephant/n02503517_1292-6.png 2 +sketch/elephant/n02503517_1292-7.png 2 +sketch/elephant/n02503517_1359-1.png 2 +sketch/elephant/n02503517_1359-2.png 2 +sketch/elephant/n02503517_1359-3.png 2 +sketch/elephant/n02503517_1359-4.png 2 +sketch/elephant/n02503517_1359-5.png 2 +sketch/elephant/n02503517_1359-6.png 2 +sketch/elephant/n02503517_1383-1.png 2 +sketch/elephant/n02503517_1383-2.png 2 +sketch/elephant/n02503517_1383-3.png 2 +sketch/elephant/n02503517_1383-4.png 2 +sketch/elephant/n02503517_1383-5.png 2 +sketch/elephant/n02503517_1383-6.png 2 +sketch/elephant/n02503517_1415-1.png 2 +sketch/elephant/n02503517_1415-2.png 2 +sketch/elephant/n02503517_1415-3.png 2 +sketch/elephant/n02503517_1415-4.png 2 +sketch/elephant/n02503517_1415-5.png 2 +sketch/elephant/n02503517_1453-1.png 2 +sketch/elephant/n02503517_1453-2.png 2 +sketch/elephant/n02503517_1453-3.png 2 +sketch/elephant/n02503517_1453-4.png 2 +sketch/elephant/n02503517_1453-5.png 2 +sketch/elephant/n02503517_1453-6.png 2 +sketch/elephant/n02503517_1583-1.png 2 +sketch/elephant/n02503517_1583-2.png 2 +sketch/elephant/n02503517_1583-3.png 2 +sketch/elephant/n02503517_1583-4.png 2 +sketch/elephant/n02503517_1583-5.png 2 +sketch/elephant/n02503517_1583-6.png 2 +sketch/elephant/n02503517_1829-1.png 2 +sketch/elephant/n02503517_1829-2.png 2 +sketch/elephant/n02503517_1829-3.png 2 +sketch/elephant/n02503517_1829-4.png 2 +sketch/elephant/n02503517_1829-5.png 2 +sketch/elephant/n02503517_1852-1.png 2 +sketch/elephant/n02503517_1852-2.png 2 +sketch/elephant/n02503517_1852-3.png 2 +sketch/elephant/n02503517_1852-4.png 2 +sketch/elephant/n02503517_1852-5.png 2 +sketch/elephant/n02503517_1963-1.png 2 +sketch/elephant/n02503517_1963-2.png 2 +sketch/elephant/n02503517_1963-3.png 2 +sketch/elephant/n02503517_1963-4.png 2 +sketch/elephant/n02503517_1963-5.png 2 +sketch/elephant/n02503517_1984-1.png 2 +sketch/elephant/n02503517_1984-2.png 2 +sketch/elephant/n02503517_1984-3.png 2 +sketch/elephant/n02503517_1984-4.png 2 +sketch/elephant/n02503517_1984-5.png 2 +sketch/elephant/n02503517_2061-1.png 2 +sketch/elephant/n02503517_2061-2.png 2 +sketch/elephant/n02503517_2061-3.png 2 +sketch/elephant/n02503517_2061-4.png 2 +sketch/elephant/n02503517_2061-5.png 2 +sketch/elephant/n02503517_2444-1.png 2 +sketch/elephant/n02503517_2444-2.png 2 +sketch/elephant/n02503517_2444-3.png 2 +sketch/elephant/n02503517_2444-4.png 2 +sketch/elephant/n02503517_2444-5.png 2 +sketch/elephant/n02503517_2547-1.png 2 +sketch/elephant/n02503517_2547-2.png 2 +sketch/elephant/n02503517_2547-3.png 2 +sketch/elephant/n02503517_2547-4.png 2 +sketch/elephant/n02503517_2547-5.png 2 +sketch/elephant/n02503517_2547-6.png 2 +sketch/elephant/n02503517_2547-7.png 2 +sketch/elephant/n02503517_2547-8.png 2 +sketch/elephant/n02503517_2547-9.png 2 +sketch/elephant/n02503517_2547-10.png 2 +sketch/elephant/n02503517_2802-1.png 2 +sketch/elephant/n02503517_2802-2.png 2 +sketch/elephant/n02503517_2802-3.png 2 +sketch/elephant/n02503517_2802-4.png 2 +sketch/elephant/n02503517_2802-5.png 2 +sketch/elephant/n02503517_2802-6.png 2 +sketch/elephant/n02503517_2804-1.png 2 +sketch/elephant/n02503517_2804-2.png 2 +sketch/elephant/n02503517_2804-3.png 2 +sketch/elephant/n02503517_2804-4.png 2 +sketch/elephant/n02503517_2804-5.png 2 +sketch/elephant/n02503517_2925-1.png 2 +sketch/elephant/n02503517_2925-2.png 2 +sketch/elephant/n02503517_2925-3.png 2 +sketch/elephant/n02503517_2925-4.png 2 +sketch/elephant/n02503517_2925-5.png 2 +sketch/elephant/n02503517_2925-6.png 2 +sketch/elephant/n02503517_2925-7.png 2 +sketch/elephant/n02503517_2925-8.png 2 +sketch/elephant/n02503517_2925-9.png 2 +sketch/elephant/n02503517_2925-10.png 2 +sketch/elephant/n02503517_2993-1.png 2 +sketch/elephant/n02503517_2993-2.png 2 +sketch/elephant/n02503517_2993-3.png 2 +sketch/elephant/n02503517_2993-4.png 2 +sketch/elephant/n02503517_2993-5.png 2 +sketch/elephant/n02503517_2993-6.png 2 +sketch/elephant/n02503517_2993-7.png 2 +sketch/elephant/n02503517_2993-8.png 2 +sketch/elephant/n02503517_2993-9.png 2 +sketch/elephant/n02503517_2993-10.png 2 +sketch/elephant/n02503517_3037-1.png 2 +sketch/elephant/n02503517_3037-2.png 2 +sketch/elephant/n02503517_3037-3.png 2 +sketch/elephant/n02503517_3037-4.png 2 +sketch/elephant/n02503517_3037-5.png 2 +sketch/elephant/n02503517_3037-6.png 2 +sketch/elephant/n02503517_3037-7.png 2 +sketch/elephant/n02503517_3037-8.png 2 +sketch/elephant/n02503517_3072-1.png 2 +sketch/elephant/n02503517_3072-2.png 2 +sketch/elephant/n02503517_3072-3.png 2 +sketch/elephant/n02503517_3072-4.png 2 +sketch/elephant/n02503517_3072-5.png 2 +sketch/elephant/n02503517_3072-6.png 2 +sketch/elephant/n02503517_3108-1.png 2 +sketch/elephant/n02503517_3108-2.png 2 +sketch/elephant/n02503517_3108-3.png 2 +sketch/elephant/n02503517_3108-4.png 2 +sketch/elephant/n02503517_3108-5.png 2 +sketch/elephant/n02503517_3108-6.png 2 +sketch/elephant/n02503517_3108-7.png 2 +sketch/elephant/n02503517_3108-8.png 2 +sketch/elephant/n02503517_3108-9.png 2 +sketch/elephant/n02503517_3799-1.png 2 +sketch/elephant/n02503517_3799-2.png 2 +sketch/elephant/n02503517_3799-3.png 2 +sketch/elephant/n02503517_3799-4.png 2 +sketch/elephant/n02503517_3799-5.png 2 +sketch/elephant/n02503517_3803-1.png 2 +sketch/elephant/n02503517_3803-2.png 2 +sketch/elephant/n02503517_3803-3.png 2 +sketch/elephant/n02503517_3803-4.png 2 +sketch/elephant/n02503517_3803-5.png 2 +sketch/elephant/n02503517_3803-6.png 2 +sketch/elephant/n02503517_3808-1.png 2 +sketch/elephant/n02503517_3808-2.png 2 +sketch/elephant/n02503517_3808-3.png 2 +sketch/elephant/n02503517_3808-4.png 2 +sketch/elephant/n02503517_3808-5.png 2 +sketch/elephant/n02503517_3808-6.png 2 +sketch/elephant/n02503517_3808-7.png 2 +sketch/elephant/n02503517_3808-8.png 2 +sketch/elephant/n02503517_3808-9.png 2 +sketch/elephant/n02503517_3808-10.png 2 +sketch/elephant/n02503517_3879-1.png 2 +sketch/elephant/n02503517_3879-2.png 2 +sketch/elephant/n02503517_3879-3.png 2 +sketch/elephant/n02503517_3879-4.png 2 +sketch/elephant/n02503517_3879-5.png 2 +sketch/elephant/n02503517_3879-6.png 2 +sketch/elephant/n02503517_3879-7.png 2 +sketch/elephant/n02503517_4221-1.png 2 +sketch/elephant/n02503517_4221-2.png 2 +sketch/elephant/n02503517_4221-3.png 2 +sketch/elephant/n02503517_4221-4.png 2 +sketch/elephant/n02503517_4221-5.png 2 +sketch/elephant/n02503517_4221-6.png 2 +sketch/elephant/n02503517_4221-7.png 2 +sketch/elephant/n02503517_4247-1.png 2 +sketch/elephant/n02503517_4247-2.png 2 +sketch/elephant/n02503517_4247-3.png 2 +sketch/elephant/n02503517_4247-4.png 2 +sketch/elephant/n02503517_4247-5.png 2 +sketch/elephant/n02503517_4247-6.png 2 +sketch/elephant/n02503517_4247-7.png 2 +sketch/elephant/n02503517_4247-8.png 2 +sketch/elephant/n02503517_4247-9.png 2 +sketch/elephant/n02503517_4247-10.png 2 +sketch/elephant/n02503517_4253-1.png 2 +sketch/elephant/n02503517_4253-2.png 2 +sketch/elephant/n02503517_4253-3.png 2 +sketch/elephant/n02503517_4253-4.png 2 +sketch/elephant/n02503517_4253-5.png 2 +sketch/elephant/n02503517_4413-1.png 2 +sketch/elephant/n02503517_4413-2.png 2 +sketch/elephant/n02503517_4413-3.png 2 +sketch/elephant/n02503517_4413-4.png 2 +sketch/elephant/n02503517_4413-5.png 2 +sketch/elephant/n02503517_4413-6.png 2 +sketch/elephant/n02503517_4413-7.png 2 +sketch/elephant/n02503517_4413-8.png 2 +sketch/elephant/n02503517_4413-9.png 2 +sketch/elephant/n02503517_4413-10.png 2 +sketch/elephant/n02503517_4605-1.png 2 +sketch/elephant/n02503517_4605-2.png 2 +sketch/elephant/n02503517_4605-3.png 2 +sketch/elephant/n02503517_4605-4.png 2 +sketch/elephant/n02503517_4605-5.png 2 +sketch/elephant/n02503517_4687-1.png 2 +sketch/elephant/n02503517_4687-2.png 2 +sketch/elephant/n02503517_4687-3.png 2 +sketch/elephant/n02503517_4687-4.png 2 +sketch/elephant/n02503517_4687-5.png 2 +sketch/elephant/n02503517_4687-6.png 2 +sketch/elephant/n02503517_5117-1.png 2 +sketch/elephant/n02503517_5117-2.png 2 +sketch/elephant/n02503517_5117-3.png 2 +sketch/elephant/n02503517_5117-4.png 2 +sketch/elephant/n02503517_5117-5.png 2 +sketch/elephant/n02503517_5117-6.png 2 +sketch/elephant/n02503517_5267-1.png 2 +sketch/elephant/n02503517_5267-2.png 2 +sketch/elephant/n02503517_5267-3.png 2 +sketch/elephant/n02503517_5267-4.png 2 +sketch/elephant/n02503517_5267-5.png 2 +sketch/elephant/n02503517_5267-6.png 2 +sketch/elephant/n02503517_5267-7.png 2 +sketch/elephant/n02503517_5287-1.png 2 +sketch/elephant/n02503517_5287-2.png 2 +sketch/elephant/n02503517_5287-3.png 2 +sketch/elephant/n02503517_5287-4.png 2 +sketch/elephant/n02503517_5287-5.png 2 +sketch/elephant/n02503517_5418-1.png 2 +sketch/elephant/n02503517_5418-2.png 2 +sketch/elephant/n02503517_5418-3.png 2 +sketch/elephant/n02503517_5418-4.png 2 +sketch/elephant/n02503517_5418-5.png 2 +sketch/elephant/n02503517_5418-6.png 2 +sketch/elephant/n02503517_5418-7.png 2 +sketch/elephant/n02503517_5418-8.png 2 +sketch/elephant/n02503517_5418-9.png 2 +sketch/elephant/n02503517_5418-10.png 2 +sketch/elephant/n02503517_5420-1.png 2 +sketch/elephant/n02503517_5420-2.png 2 +sketch/elephant/n02503517_5420-3.png 2 +sketch/elephant/n02503517_5420-4.png 2 +sketch/elephant/n02503517_5420-5.png 2 +sketch/elephant/n02503517_5420-6.png 2 +sketch/elephant/n02503517_5420-7.png 2 +sketch/elephant/n02503517_5527-1.png 2 +sketch/elephant/n02503517_5527-2.png 2 +sketch/elephant/n02503517_5527-3.png 2 +sketch/elephant/n02503517_5527-4.png 2 +sketch/elephant/n02503517_5527-5.png 2 +sketch/elephant/n02503517_5527-6.png 2 +sketch/elephant/n02503517_5892-1.png 2 +sketch/elephant/n02503517_5892-2.png 2 +sketch/elephant/n02503517_5892-3.png 2 +sketch/elephant/n02503517_5892-4.png 2 +sketch/elephant/n02503517_5892-5.png 2 +sketch/elephant/n02503517_5892-6.png 2 +sketch/elephant/n02503517_5892-7.png 2 +sketch/elephant/n02503517_5905-2.png 2 +sketch/elephant/n02503517_5905-3.png 2 +sketch/elephant/n02503517_5905-4.png 2 +sketch/elephant/n02503517_5905-5.png 2 +sketch/elephant/n02503517_5905-6.png 2 +sketch/elephant/n02503517_5905-7.png 2 +sketch/elephant/n02503517_5905-8.png 2 +sketch/elephant/n02503517_5905-9.png 2 +sketch/elephant/n02503517_5905-10.png 2 +sketch/elephant/n02503517_5905-11.png 2 +sketch/elephant/n02503517_5909-1.png 2 +sketch/elephant/n02503517_5909-2.png 2 +sketch/elephant/n02503517_5909-3.png 2 +sketch/elephant/n02503517_5909-4.png 2 +sketch/elephant/n02503517_5909-5.png 2 +sketch/elephant/n02503517_6032-1.png 2 +sketch/elephant/n02503517_6032-2.png 2 +sketch/elephant/n02503517_6032-3.png 2 +sketch/elephant/n02503517_6032-4.png 2 +sketch/elephant/n02503517_6032-5.png 2 +sketch/elephant/n02503517_6032-6.png 2 +sketch/elephant/n02503517_6043-1.png 2 +sketch/elephant/n02503517_6043-2.png 2 +sketch/elephant/n02503517_6043-3.png 2 +sketch/elephant/n02503517_6043-4.png 2 +sketch/elephant/n02503517_6043-5.png 2 +sketch/elephant/n02503517_6043-6.png 2 +sketch/elephant/n02503517_6232-1.png 2 +sketch/elephant/n02503517_6232-2.png 2 +sketch/elephant/n02503517_6232-3.png 2 +sketch/elephant/n02503517_6232-4.png 2 +sketch/elephant/n02503517_6232-5.png 2 +sketch/elephant/n02503517_6232-6.png 2 +sketch/elephant/n02503517_6232-7.png 2 +sketch/elephant/n02503517_6396-1.png 2 +sketch/elephant/n02503517_6396-2.png 2 +sketch/elephant/n02503517_6396-3.png 2 +sketch/elephant/n02503517_6396-4.png 2 +sketch/elephant/n02503517_6396-5.png 2 +sketch/elephant/n02503517_6429-1.png 2 +sketch/elephant/n02503517_6429-2.png 2 +sketch/elephant/n02503517_6429-3.png 2 +sketch/elephant/n02503517_6429-4.png 2 +sketch/elephant/n02503517_6429-5.png 2 +sketch/elephant/n02503517_6479-1.png 2 +sketch/elephant/n02503517_6479-2.png 2 +sketch/elephant/n02503517_6479-3.png 2 +sketch/elephant/n02503517_6479-4.png 2 +sketch/elephant/n02503517_6479-5.png 2 +sketch/elephant/n02503517_6479-6.png 2 +sketch/elephant/n02503517_6479-7.png 2 +sketch/elephant/n02503517_6479-8.png 2 +sketch/elephant/n02503517_6511-1.png 2 +sketch/elephant/n02503517_6511-2.png 2 +sketch/elephant/n02503517_6511-3.png 2 +sketch/elephant/n02503517_6511-4.png 2 +sketch/elephant/n02503517_6511-5.png 2 +sketch/elephant/n02503517_6611-1.png 2 +sketch/elephant/n02503517_6611-2.png 2 +sketch/elephant/n02503517_6611-3.png 2 +sketch/elephant/n02503517_6611-4.png 2 +sketch/elephant/n02503517_6611-5.png 2 +sketch/elephant/n02503517_6611-6.png 2 +sketch/elephant/n02503517_6611-7.png 2 +sketch/elephant/n02503517_6611-8.png 2 +sketch/elephant/n02503517_6611-9.png 2 +sketch/elephant/n02503517_6611-10.png 2 +sketch/elephant/n02503517_6613-1.png 2 +sketch/elephant/n02503517_6613-2.png 2 +sketch/elephant/n02503517_6613-3.png 2 +sketch/elephant/n02503517_6613-4.png 2 +sketch/elephant/n02503517_6613-5.png 2 +sketch/elephant/n02503517_6624-1.png 2 +sketch/elephant/n02503517_6624-2.png 2 +sketch/elephant/n02503517_6624-3.png 2 +sketch/elephant/n02503517_6624-4.png 2 +sketch/elephant/n02503517_6624-5.png 2 +sketch/elephant/n02503517_6624-6.png 2 +sketch/elephant/n02503517_6661-1.png 2 +sketch/elephant/n02503517_6661-2.png 2 +sketch/elephant/n02503517_6661-3.png 2 +sketch/elephant/n02503517_6661-4.png 2 +sketch/elephant/n02503517_6661-5.png 2 +sketch/elephant/n02503517_6784-1.png 2 +sketch/elephant/n02503517_6784-2.png 2 +sketch/elephant/n02503517_6784-3.png 2 +sketch/elephant/n02503517_6784-4.png 2 +sketch/elephant/n02503517_6784-5.png 2 +sketch/elephant/n02503517_6880-1.png 2 +sketch/elephant/n02503517_6880-2.png 2 +sketch/elephant/n02503517_6880-3.png 2 +sketch/elephant/n02503517_6880-4.png 2 +sketch/elephant/n02503517_6880-5.png 2 +sketch/elephant/n02503517_6937-1.png 2 +sketch/elephant/n02503517_6937-2.png 2 +sketch/elephant/n02503517_6937-3.png 2 +sketch/elephant/n02503517_6937-4.png 2 +sketch/elephant/n02503517_6937-5.png 2 +sketch/elephant/n02503517_6937-6.png 2 +sketch/elephant/n02503517_7020-1.png 2 +sketch/elephant/n02503517_7020-2.png 2 +sketch/elephant/n02503517_7020-3.png 2 +sketch/elephant/n02503517_7020-4.png 2 +sketch/elephant/n02503517_7020-5.png 2 +sketch/elephant/n02503517_7020-6.png 2 +sketch/elephant/n02503517_7031-1.png 2 +sketch/elephant/n02503517_7031-2.png 2 +sketch/elephant/n02503517_7031-3.png 2 +sketch/elephant/n02503517_7031-4.png 2 +sketch/elephant/n02503517_7031-5.png 2 +sketch/elephant/n02503517_7031-6.png 2 +sketch/elephant/n02503517_7031-7.png 2 +sketch/elephant/n02503517_7031-8.png 2 +sketch/elephant/n02503517_7031-9.png 2 +sketch/elephant/n02503517_7031-10.png 2 +sketch/elephant/n02503517_7083-1.png 2 +sketch/elephant/n02503517_7083-2.png 2 +sketch/elephant/n02503517_7083-3.png 2 +sketch/elephant/n02503517_7083-4.png 2 +sketch/elephant/n02503517_7083-5.png 2 +sketch/elephant/n02503517_7173-1.png 2 +sketch/elephant/n02503517_7173-2.png 2 +sketch/elephant/n02503517_7173-3.png 2 +sketch/elephant/n02503517_7173-4.png 2 +sketch/elephant/n02503517_7173-5.png 2 +sketch/elephant/n02503517_7211-1.png 2 +sketch/elephant/n02503517_7211-2.png 2 +sketch/elephant/n02503517_7211-3.png 2 +sketch/elephant/n02503517_7211-4.png 2 +sketch/elephant/n02503517_7211-5.png 2 +sketch/elephant/n02503517_7393-1.png 2 +sketch/elephant/n02503517_7393-2.png 2 +sketch/elephant/n02503517_7393-3.png 2 +sketch/elephant/n02503517_7393-4.png 2 +sketch/elephant/n02503517_7393-5.png 2 +sketch/elephant/n02503517_7393-6.png 2 +sketch/elephant/n02503517_7393-7.png 2 +sketch/elephant/n02503517_7592-1.png 2 +sketch/elephant/n02503517_7592-2.png 2 +sketch/elephant/n02503517_7592-3.png 2 +sketch/elephant/n02503517_7592-4.png 2 +sketch/elephant/n02503517_7592-5.png 2 +sketch/elephant/n02503517_7592-6.png 2 +sketch/elephant/n02503517_7592-7.png 2 +sketch/elephant/n02503517_7592-8.png 2 +sketch/elephant/n02503517_8137-1.png 2 +sketch/elephant/n02503517_8137-2.png 2 +sketch/elephant/n02503517_8137-3.png 2 +sketch/elephant/n02503517_8137-4.png 2 +sketch/elephant/n02503517_8137-5.png 2 +sketch/elephant/n02503517_8205-1.png 2 +sketch/elephant/n02503517_8205-2.png 2 +sketch/elephant/n02503517_8205-3.png 2 +sketch/elephant/n02503517_8205-4.png 2 +sketch/elephant/n02503517_8205-5.png 2 +sketch/elephant/n02503517_8222-1.png 2 +sketch/elephant/n02503517_8222-2.png 2 +sketch/elephant/n02503517_8222-3.png 2 +sketch/elephant/n02503517_8222-4.png 2 +sketch/elephant/n02503517_8222-5.png 2 +sketch/elephant/n02503517_8265-1.png 2 +sketch/elephant/n02503517_8265-2.png 2 +sketch/elephant/n02503517_8265-3.png 2 +sketch/elephant/n02503517_8265-4.png 2 +sketch/elephant/n02503517_8265-5.png 2 +sketch/elephant/n02503517_8292-1.png 2 +sketch/elephant/n02503517_8292-2.png 2 +sketch/elephant/n02503517_8292-3.png 2 +sketch/elephant/n02503517_8292-4.png 2 +sketch/elephant/n02503517_8292-5.png 2 +sketch/elephant/n02503517_8292-6.png 2 +sketch/elephant/n02503517_8518-1.png 2 +sketch/elephant/n02503517_8518-2.png 2 +sketch/elephant/n02503517_8518-3.png 2 +sketch/elephant/n02503517_8518-4.png 2 +sketch/elephant/n02503517_8518-5.png 2 +sketch/elephant/n02503517_8518-6.png 2 +sketch/elephant/n02503517_8571-1.png 2 +sketch/elephant/n02503517_8571-2.png 2 +sketch/elephant/n02503517_8571-3.png 2 +sketch/elephant/n02503517_8571-4.png 2 +sketch/elephant/n02503517_8571-5.png 2 +sketch/elephant/n02503517_8571-6.png 2 +sketch/elephant/n02503517_8757-1.png 2 +sketch/elephant/n02503517_8757-2.png 2 +sketch/elephant/n02503517_8757-3.png 2 +sketch/elephant/n02503517_8757-4.png 2 +sketch/elephant/n02503517_8757-5.png 2 +sketch/elephant/n02503517_8757-6.png 2 +sketch/elephant/n02503517_8901-1.png 2 +sketch/elephant/n02503517_8901-2.png 2 +sketch/elephant/n02503517_8901-3.png 2 +sketch/elephant/n02503517_8901-4.png 2 +sketch/elephant/n02503517_8901-5.png 2 +sketch/elephant/n02503517_8901-6.png 2 +sketch/elephant/n02503517_8901-7.png 2 +sketch/elephant/n02503517_8904-1.png 2 +sketch/elephant/n02503517_8904-2.png 2 +sketch/elephant/n02503517_8904-3.png 2 +sketch/elephant/n02503517_8904-4.png 2 +sketch/elephant/n02503517_8904-5.png 2 +sketch/elephant/n02503517_8904-6.png 2 +sketch/elephant/n02503517_8938-1.png 2 +sketch/elephant/n02503517_8938-2.png 2 +sketch/elephant/n02503517_8938-3.png 2 +sketch/elephant/n02503517_8938-4.png 2 +sketch/elephant/n02503517_8938-5.png 2 +sketch/elephant/n02503517_8938-6.png 2 +sketch/elephant/n02503517_9043-1.png 2 +sketch/elephant/n02503517_9043-2.png 2 +sketch/elephant/n02503517_9043-3.png 2 +sketch/elephant/n02503517_9043-4.png 2 +sketch/elephant/n02503517_9043-5.png 2 +sketch/elephant/n02503517_9043-6.png 2 +sketch/elephant/n02503517_9043-7.png 2 +sketch/elephant/n02503517_9043-8.png 2 +sketch/elephant/n02503517_9043-9.png 2 +sketch/elephant/n02503517_9043-10.png 2 +sketch/elephant/n02503517_9154-1.png 2 +sketch/elephant/n02503517_9154-2.png 2 +sketch/elephant/n02503517_9154-3.png 2 +sketch/elephant/n02503517_9154-4.png 2 +sketch/elephant/n02503517_9154-5.png 2 +sketch/elephant/n02503517_9154-6.png 2 +sketch/elephant/n02503517_9237-1.png 2 +sketch/elephant/n02503517_9237-2.png 2 +sketch/elephant/n02503517_9237-3.png 2 +sketch/elephant/n02503517_9237-4.png 2 +sketch/elephant/n02503517_9237-5.png 2 +sketch/elephant/n02503517_9237-6.png 2 +sketch/elephant/n02503517_9237-7.png 2 +sketch/elephant/n02503517_9241-1.png 2 +sketch/elephant/n02503517_9241-2.png 2 +sketch/elephant/n02503517_9241-3.png 2 +sketch/elephant/n02503517_9241-4.png 2 +sketch/elephant/n02503517_9241-5.png 2 +sketch/elephant/n02503517_9270-1.png 2 +sketch/elephant/n02503517_9270-2.png 2 +sketch/elephant/n02503517_9270-3.png 2 +sketch/elephant/n02503517_9270-4.png 2 +sketch/elephant/n02503517_9270-5.png 2 +sketch/elephant/n02503517_9270-6.png 2 +sketch/elephant/n02503517_9270-7.png 2 +sketch/elephant/n02503517_9270-8.png 2 +sketch/elephant/n02503517_9270-9.png 2 +sketch/elephant/n02503517_9270-10.png 2 +sketch/elephant/n02503517_9421-1.png 2 +sketch/elephant/n02503517_9421-2.png 2 +sketch/elephant/n02503517_9421-3.png 2 +sketch/elephant/n02503517_9421-4.png 2 +sketch/elephant/n02503517_9421-5.png 2 +sketch/elephant/n02503517_9421-6.png 2 +sketch/elephant/n02503517_9421-7.png 2 +sketch/elephant/n02503517_9421-8.png 2 +sketch/elephant/n02503517_9421-9.png 2 +sketch/elephant/n02503517_9827-1.png 2 +sketch/elephant/n02503517_9827-2.png 2 +sketch/elephant/n02503517_9827-3.png 2 +sketch/elephant/n02503517_9827-4.png 2 +sketch/elephant/n02503517_9827-5.png 2 +sketch/elephant/n02503517_9827-6.png 2 +sketch/elephant/n02503517_9827-7.png 2 +sketch/elephant/n02503517_9827-8.png 2 +sketch/elephant/n02503517_10036-1.png 2 +sketch/elephant/n02503517_10036-2.png 2 +sketch/elephant/n02503517_10036-3.png 2 +sketch/elephant/n02503517_10036-4.png 2 +sketch/elephant/n02503517_10036-5.png 2 +sketch/elephant/n02503517_10036-6.png 2 +sketch/elephant/n02503517_10036-7.png 2 +sketch/elephant/n02503517_10036-8.png 2 +sketch/elephant/n02503517_10036-9.png 2 +sketch/elephant/n02503517_10036-10.png 2 +sketch/elephant/n02503517_10075-1.png 2 +sketch/elephant/n02503517_10075-2.png 2 +sketch/elephant/n02503517_10075-3.png 2 +sketch/elephant/n02503517_10075-4.png 2 +sketch/elephant/n02503517_10075-5.png 2 +sketch/elephant/n02503517_10193-1.png 2 +sketch/elephant/n02503517_10193-2.png 2 +sketch/elephant/n02503517_10193-3.png 2 +sketch/elephant/n02503517_10193-4.png 2 +sketch/elephant/n02503517_10193-5.png 2 +sketch/elephant/n02503517_10193-6.png 2 +sketch/elephant/n02503517_10193-7.png 2 +sketch/elephant/n02503517_10193-8.png 2 +sketch/elephant/n02503517_10193-9.png 2 +sketch/elephant/n02503517_10193-10.png 2 +sketch/elephant/n02503517_10259-1.png 2 +sketch/elephant/n02503517_10259-2.png 2 +sketch/elephant/n02503517_10259-3.png 2 +sketch/elephant/n02503517_10259-4.png 2 +sketch/elephant/n02503517_10259-5.png 2 +sketch/elephant/n02503517_10259-6.png 2 +sketch/elephant/n02503517_10259-7.png 2 +sketch/elephant/n02503517_10259-8.png 2 +sketch/elephant/n02503517_10259-9.png 2 +sketch/elephant/n02503517_10275-1.png 2 +sketch/elephant/n02503517_10275-2.png 2 +sketch/elephant/n02503517_10275-3.png 2 +sketch/elephant/n02503517_10275-4.png 2 +sketch/elephant/n02503517_10275-5.png 2 +sketch/elephant/n02503517_10275-6.png 2 +sketch/elephant/n02503517_10300-1.png 2 +sketch/elephant/n02503517_10300-2.png 2 +sketch/elephant/n02503517_10300-3.png 2 +sketch/elephant/n02503517_10300-4.png 2 +sketch/elephant/n02503517_10300-5.png 2 +sketch/elephant/n02503517_10439-1.png 2 +sketch/elephant/n02503517_10439-2.png 2 +sketch/elephant/n02503517_10439-3.png 2 +sketch/elephant/n02503517_10439-4.png 2 +sketch/elephant/n02503517_10439-5.png 2 +sketch/elephant/n02503517_10439-6.png 2 +sketch/elephant/n02503517_10439-7.png 2 +sketch/elephant/n02503517_10439-8.png 2 +sketch/elephant/n02503517_10440-1.png 2 +sketch/elephant/n02503517_10440-2.png 2 +sketch/elephant/n02503517_10440-3.png 2 +sketch/elephant/n02503517_10440-4.png 2 +sketch/elephant/n02503517_10440-5.png 2 +sketch/elephant/n02503517_10440-6.png 2 +sketch/elephant/n02503517_10440-7.png 2 +sketch/elephant/n02503517_10440-8.png 2 +sketch/elephant/n02503517_10440-9.png 2 +sketch/elephant/n02503517_10528-1.png 2 +sketch/elephant/n02503517_10528-2.png 2 +sketch/elephant/n02503517_10528-3.png 2 +sketch/elephant/n02503517_10528-4.png 2 +sketch/elephant/n02503517_10528-5.png 2 +sketch/elephant/n02503517_10558-1.png 2 +sketch/elephant/n02503517_10558-2.png 2 +sketch/elephant/n02503517_10558-3.png 2 +sketch/elephant/n02503517_10558-4.png 2 +sketch/elephant/n02503517_10558-5.png 2 +sketch/elephant/n02503517_10778-1.png 2 +sketch/elephant/n02503517_10778-2.png 2 +sketch/elephant/n02503517_10778-3.png 2 +sketch/elephant/n02503517_10778-4.png 2 +sketch/elephant/n02503517_10778-5.png 2 +sketch/elephant/n02503517_10778-6.png 2 +sketch/elephant/n02503517_11873-1.png 2 +sketch/elephant/n02503517_11873-2.png 2 +sketch/elephant/n02503517_11873-3.png 2 +sketch/elephant/n02503517_11873-4.png 2 +sketch/elephant/n02503517_11873-5.png 2 +sketch/elephant/n02503517_11873-6.png 2 +sketch/elephant/n02503517_11873-7.png 2 +sketch/elephant/n02503517_11873-8.png 2 +sketch/elephant/n02503517_11873-9.png 2 +sketch/elephant/n02503517_12688-1.png 2 +sketch/elephant/n02503517_12688-2.png 2 +sketch/elephant/n02503517_12688-3.png 2 +sketch/elephant/n02503517_12688-4.png 2 +sketch/elephant/n02503517_12688-5.png 2 +sketch/elephant/5921.png 2 +sketch/elephant/5922.png 2 +sketch/elephant/5923.png 2 +sketch/elephant/5924.png 2 +sketch/elephant/5925.png 2 +sketch/elephant/5926.png 2 +sketch/elephant/5927.png 2 +sketch/elephant/5928.png 2 +sketch/elephant/5929.png 2 +sketch/elephant/5930.png 2 +sketch/elephant/5931.png 2 +sketch/elephant/5932.png 2 +sketch/elephant/5933.png 2 +sketch/elephant/5934.png 2 +sketch/elephant/5935.png 2 +sketch/elephant/5936.png 2 +sketch/elephant/5937.png 2 +sketch/elephant/5938.png 2 +sketch/elephant/5939.png 2 +sketch/elephant/5940.png 2 +sketch/elephant/5941.png 2 +sketch/elephant/5942.png 2 +sketch/elephant/5943.png 2 +sketch/elephant/5944.png 2 +sketch/elephant/5945.png 2 +sketch/elephant/5946.png 2 +sketch/elephant/5947.png 2 +sketch/elephant/5948.png 2 +sketch/elephant/5949.png 2 +sketch/elephant/5950.png 2 +sketch/elephant/5951.png 2 +sketch/elephant/5952.png 2 +sketch/elephant/5953.png 2 +sketch/elephant/5954.png 2 +sketch/elephant/5955.png 2 +sketch/elephant/5956.png 2 +sketch/elephant/5957.png 2 +sketch/elephant/5958.png 2 +sketch/elephant/5959.png 2 +sketch/elephant/5960.png 2 +sketch/elephant/5961.png 2 +sketch/elephant/5962.png 2 +sketch/elephant/5963.png 2 +sketch/elephant/5964.png 2 +sketch/elephant/5965.png 2 +sketch/elephant/5966.png 2 +sketch/elephant/5967.png 2 +sketch/elephant/5968.png 2 +sketch/elephant/5969.png 2 +sketch/elephant/5970.png 2 +sketch/elephant/5971.png 2 +sketch/elephant/5972.png 2 +sketch/elephant/5973.png 2 +sketch/elephant/5974.png 2 +sketch/elephant/5975.png 2 +sketch/elephant/5976.png 2 +sketch/elephant/5977.png 2 +sketch/elephant/5978.png 2 +sketch/elephant/5979.png 2 +sketch/elephant/5980.png 2 +sketch/elephant/5981.png 2 +sketch/elephant/5982.png 2 +sketch/elephant/5983.png 2 +sketch/elephant/5984.png 2 +sketch/elephant/5985.png 2 +sketch/elephant/5986.png 2 +sketch/elephant/5987.png 2 +sketch/elephant/5988.png 2 +sketch/elephant/5989.png 2 +sketch/elephant/5990.png 2 +sketch/elephant/5991.png 2 +sketch/elephant/5992.png 2 +sketch/elephant/5993.png 2 +sketch/elephant/5994.png 2 +sketch/elephant/5995.png 2 +sketch/elephant/5996.png 2 +sketch/elephant/5997.png 2 +sketch/elephant/5998.png 2 +sketch/elephant/5999.png 2 +sketch/elephant/6000.png 2 +sketch/giraffe/n02439033_67-1.png 3 +sketch/giraffe/n02439033_67-2.png 3 +sketch/giraffe/n02439033_67-3.png 3 +sketch/giraffe/n02439033_67-4.png 3 +sketch/giraffe/n02439033_67-5.png 3 +sketch/giraffe/n02439033_67-6.png 3 +sketch/giraffe/n02439033_67-7.png 3 +sketch/giraffe/n02439033_221-1.png 3 +sketch/giraffe/n02439033_221-2.png 3 +sketch/giraffe/n02439033_221-3.png 3 +sketch/giraffe/n02439033_221-4.png 3 +sketch/giraffe/n02439033_221-5.png 3 +sketch/giraffe/n02439033_221-6.png 3 +sketch/giraffe/n02439033_376-1.png 3 +sketch/giraffe/n02439033_376-2.png 3 +sketch/giraffe/n02439033_376-3.png 3 +sketch/giraffe/n02439033_376-4.png 3 +sketch/giraffe/n02439033_376-5.png 3 +sketch/giraffe/n02439033_569-1.png 3 +sketch/giraffe/n02439033_569-2.png 3 +sketch/giraffe/n02439033_569-3.png 3 +sketch/giraffe/n02439033_569-4.png 3 +sketch/giraffe/n02439033_569-5.png 3 +sketch/giraffe/n02439033_628-1.png 3 +sketch/giraffe/n02439033_628-2.png 3 +sketch/giraffe/n02439033_628-3.png 3 +sketch/giraffe/n02439033_628-4.png 3 +sketch/giraffe/n02439033_628-5.png 3 +sketch/giraffe/n02439033_628-6.png 3 +sketch/giraffe/n02439033_628-7.png 3 +sketch/giraffe/n02439033_628-8.png 3 +sketch/giraffe/n02439033_628-9.png 3 +sketch/giraffe/n02439033_628-10.png 3 +sketch/giraffe/n02439033_866-1.png 3 +sketch/giraffe/n02439033_866-2.png 3 +sketch/giraffe/n02439033_866-3.png 3 +sketch/giraffe/n02439033_866-4.png 3 +sketch/giraffe/n02439033_866-5.png 3 +sketch/giraffe/n02439033_866-6.png 3 +sketch/giraffe/n02439033_991-1.png 3 +sketch/giraffe/n02439033_991-2.png 3 +sketch/giraffe/n02439033_991-3.png 3 +sketch/giraffe/n02439033_991-4.png 3 +sketch/giraffe/n02439033_991-5.png 3 +sketch/giraffe/n02439033_991-6.png 3 +sketch/giraffe/n02439033_991-7.png 3 +sketch/giraffe/n02439033_991-8.png 3 +sketch/giraffe/n02439033_991-9.png 3 +sketch/giraffe/n02439033_1327-1.png 3 +sketch/giraffe/n02439033_1327-2.png 3 +sketch/giraffe/n02439033_1327-3.png 3 +sketch/giraffe/n02439033_1327-4.png 3 +sketch/giraffe/n02439033_1327-5.png 3 +sketch/giraffe/n02439033_1508-1.png 3 +sketch/giraffe/n02439033_1508-2.png 3 +sketch/giraffe/n02439033_1508-3.png 3 +sketch/giraffe/n02439033_1508-4.png 3 +sketch/giraffe/n02439033_1508-5.png 3 +sketch/giraffe/n02439033_1508-6.png 3 +sketch/giraffe/n02439033_1508-7.png 3 +sketch/giraffe/n02439033_1508-8.png 3 +sketch/giraffe/n02439033_1508-9.png 3 +sketch/giraffe/n02439033_2486-1.png 3 +sketch/giraffe/n02439033_2486-2.png 3 +sketch/giraffe/n02439033_2486-3.png 3 +sketch/giraffe/n02439033_2486-4.png 3 +sketch/giraffe/n02439033_2486-5.png 3 +sketch/giraffe/n02439033_2486-6.png 3 +sketch/giraffe/n02439033_2500-1.png 3 +sketch/giraffe/n02439033_2500-2.png 3 +sketch/giraffe/n02439033_2500-3.png 3 +sketch/giraffe/n02439033_2500-4.png 3 +sketch/giraffe/n02439033_2500-5.png 3 +sketch/giraffe/n02439033_2500-6.png 3 +sketch/giraffe/n02439033_2677-1.png 3 +sketch/giraffe/n02439033_2677-2.png 3 +sketch/giraffe/n02439033_2677-3.png 3 +sketch/giraffe/n02439033_2677-4.png 3 +sketch/giraffe/n02439033_2677-5.png 3 +sketch/giraffe/n02439033_2677-6.png 3 +sketch/giraffe/n02439033_2677-7.png 3 +sketch/giraffe/n02439033_3944-1.png 3 +sketch/giraffe/n02439033_3944-2.png 3 +sketch/giraffe/n02439033_3944-3.png 3 +sketch/giraffe/n02439033_3944-4.png 3 +sketch/giraffe/n02439033_3944-5.png 3 +sketch/giraffe/n02439033_3944-6.png 3 +sketch/giraffe/n02439033_3944-7.png 3 +sketch/giraffe/n02439033_3944-8.png 3 +sketch/giraffe/n02439033_3944-9.png 3 +sketch/giraffe/n02439033_3944-10.png 3 +sketch/giraffe/n02439033_4601-1.png 3 +sketch/giraffe/n02439033_4601-2.png 3 +sketch/giraffe/n02439033_4601-3.png 3 +sketch/giraffe/n02439033_4601-4.png 3 +sketch/giraffe/n02439033_4601-5.png 3 +sketch/giraffe/n02439033_5004-1.png 3 +sketch/giraffe/n02439033_5004-2.png 3 +sketch/giraffe/n02439033_5004-3.png 3 +sketch/giraffe/n02439033_5004-4.png 3 +sketch/giraffe/n02439033_5004-5.png 3 +sketch/giraffe/n02439033_5004-6.png 3 +sketch/giraffe/n02439033_5004-7.png 3 +sketch/giraffe/n02439033_5004-8.png 3 +sketch/giraffe/n02439033_5652-1.png 3 +sketch/giraffe/n02439033_5652-2.png 3 +sketch/giraffe/n02439033_5652-3.png 3 +sketch/giraffe/n02439033_5652-4.png 3 +sketch/giraffe/n02439033_5652-5.png 3 +sketch/giraffe/n02439033_6552-1.png 3 +sketch/giraffe/n02439033_6552-2.png 3 +sketch/giraffe/n02439033_6552-3.png 3 +sketch/giraffe/n02439033_6552-4.png 3 +sketch/giraffe/n02439033_6552-5.png 3 +sketch/giraffe/n02439033_8789-1.png 3 +sketch/giraffe/n02439033_8789-2.png 3 +sketch/giraffe/n02439033_8789-3.png 3 +sketch/giraffe/n02439033_8789-4.png 3 +sketch/giraffe/n02439033_8789-5.png 3 +sketch/giraffe/n02439033_8846-1.png 3 +sketch/giraffe/n02439033_8846-2.png 3 +sketch/giraffe/n02439033_8846-3.png 3 +sketch/giraffe/n02439033_8846-4.png 3 +sketch/giraffe/n02439033_8846-5.png 3 +sketch/giraffe/n02439033_8846-6.png 3 +sketch/giraffe/n02439033_8846-7.png 3 +sketch/giraffe/n02439033_8846-8.png 3 +sketch/giraffe/n02439033_8846-9.png 3 +sketch/giraffe/n02439033_8846-10.png 3 +sketch/giraffe/n02439033_8846-11.png 3 +sketch/giraffe/n02439033_8846-12.png 3 +sketch/giraffe/n02439033_8846-13.png 3 +sketch/giraffe/n02439033_8875-1.png 3 +sketch/giraffe/n02439033_8875-2.png 3 +sketch/giraffe/n02439033_8875-3.png 3 +sketch/giraffe/n02439033_8875-4.png 3 +sketch/giraffe/n02439033_8875-5.png 3 +sketch/giraffe/n02439033_8875-6.png 3 +sketch/giraffe/n02439033_8875-7.png 3 +sketch/giraffe/n02439033_8875-8.png 3 +sketch/giraffe/n02439033_9257-1.png 3 +sketch/giraffe/n02439033_9257-2.png 3 +sketch/giraffe/n02439033_9257-3.png 3 +sketch/giraffe/n02439033_9257-4.png 3 +sketch/giraffe/n02439033_9257-5.png 3 +sketch/giraffe/n02439033_9257-6.png 3 +sketch/giraffe/n02439033_9261-1.png 3 +sketch/giraffe/n02439033_9261-2.png 3 +sketch/giraffe/n02439033_9261-3.png 3 +sketch/giraffe/n02439033_9261-4.png 3 +sketch/giraffe/n02439033_9261-5.png 3 +sketch/giraffe/n02439033_9398-1.png 3 +sketch/giraffe/n02439033_9398-2.png 3 +sketch/giraffe/n02439033_9398-3.png 3 +sketch/giraffe/n02439033_9398-4.png 3 +sketch/giraffe/n02439033_9398-5.png 3 +sketch/giraffe/n02439033_9398-6.png 3 +sketch/giraffe/n02439033_9472-1.png 3 +sketch/giraffe/n02439033_9472-2.png 3 +sketch/giraffe/n02439033_9472-3.png 3 +sketch/giraffe/n02439033_9472-4.png 3 +sketch/giraffe/n02439033_9472-5.png 3 +sketch/giraffe/n02439033_9472-6.png 3 +sketch/giraffe/n02439033_9472-7.png 3 +sketch/giraffe/n02439033_9472-8.png 3 +sketch/giraffe/n02439033_9472-9.png 3 +sketch/giraffe/n02439033_9472-10.png 3 +sketch/giraffe/n02439033_9598-1.png 3 +sketch/giraffe/n02439033_9598-2.png 3 +sketch/giraffe/n02439033_9598-3.png 3 +sketch/giraffe/n02439033_9598-4.png 3 +sketch/giraffe/n02439033_9598-5.png 3 +sketch/giraffe/n02439033_9598-6.png 3 +sketch/giraffe/n02439033_9598-7.png 3 +sketch/giraffe/n02439033_9598-8.png 3 +sketch/giraffe/n02439033_9598-9.png 3 +sketch/giraffe/n02439033_9598-10.png 3 +sketch/giraffe/n02439033_9604-1.png 3 +sketch/giraffe/n02439033_9604-2.png 3 +sketch/giraffe/n02439033_9604-3.png 3 +sketch/giraffe/n02439033_9604-4.png 3 +sketch/giraffe/n02439033_9604-5.png 3 +sketch/giraffe/n02439033_9679-1.png 3 +sketch/giraffe/n02439033_9679-2.png 3 +sketch/giraffe/n02439033_9679-3.png 3 +sketch/giraffe/n02439033_9679-4.png 3 +sketch/giraffe/n02439033_9679-5.png 3 +sketch/giraffe/n02439033_9719-1.png 3 +sketch/giraffe/n02439033_9719-2.png 3 +sketch/giraffe/n02439033_9719-3.png 3 +sketch/giraffe/n02439033_9719-4.png 3 +sketch/giraffe/n02439033_9719-5.png 3 +sketch/giraffe/n02439033_9719-6.png 3 +sketch/giraffe/n02439033_9719-7.png 3 +sketch/giraffe/n02439033_9719-8.png 3 +sketch/giraffe/n02439033_9719-9.png 3 +sketch/giraffe/n02439033_10130-1.png 3 +sketch/giraffe/n02439033_10130-2.png 3 +sketch/giraffe/n02439033_10130-3.png 3 +sketch/giraffe/n02439033_10130-4.png 3 +sketch/giraffe/n02439033_10130-5.png 3 +sketch/giraffe/n02439033_10130-6.png 3 +sketch/giraffe/n02439033_10130-7.png 3 +sketch/giraffe/n02439033_10164-1.png 3 +sketch/giraffe/n02439033_10164-2.png 3 +sketch/giraffe/n02439033_10164-3.png 3 +sketch/giraffe/n02439033_10164-4.png 3 +sketch/giraffe/n02439033_10164-5.png 3 +sketch/giraffe/n02439033_10164-6.png 3 +sketch/giraffe/n02439033_10164-7.png 3 +sketch/giraffe/n02439033_10164-8.png 3 +sketch/giraffe/n02439033_10164-9.png 3 +sketch/giraffe/n02439033_10164-10.png 3 +sketch/giraffe/n02439033_10279-1.png 3 +sketch/giraffe/n02439033_10279-2.png 3 +sketch/giraffe/n02439033_10279-3.png 3 +sketch/giraffe/n02439033_10279-4.png 3 +sketch/giraffe/n02439033_10279-5.png 3 +sketch/giraffe/n02439033_10279-6.png 3 +sketch/giraffe/n02439033_10295-1.png 3 +sketch/giraffe/n02439033_10295-2.png 3 +sketch/giraffe/n02439033_10295-3.png 3 +sketch/giraffe/n02439033_10295-4.png 3 +sketch/giraffe/n02439033_10295-5.png 3 +sketch/giraffe/n02439033_10453-1.png 3 +sketch/giraffe/n02439033_10453-2.png 3 +sketch/giraffe/n02439033_10453-3.png 3 +sketch/giraffe/n02439033_10453-4.png 3 +sketch/giraffe/n02439033_10453-5.png 3 +sketch/giraffe/n02439033_10453-6.png 3 +sketch/giraffe/n02439033_10491-1.png 3 +sketch/giraffe/n02439033_10491-2.png 3 +sketch/giraffe/n02439033_10491-3.png 3 +sketch/giraffe/n02439033_10491-4.png 3 +sketch/giraffe/n02439033_10491-5.png 3 +sketch/giraffe/n02439033_10491-6.png 3 +sketch/giraffe/n02439033_10541-1.png 3 +sketch/giraffe/n02439033_10541-2.png 3 +sketch/giraffe/n02439033_10541-3.png 3 +sketch/giraffe/n02439033_10541-4.png 3 +sketch/giraffe/n02439033_10541-5.png 3 +sketch/giraffe/n02439033_10541-6.png 3 +sketch/giraffe/n02439033_10616-1.png 3 +sketch/giraffe/n02439033_10616-2.png 3 +sketch/giraffe/n02439033_10616-3.png 3 +sketch/giraffe/n02439033_10616-4.png 3 +sketch/giraffe/n02439033_10616-5.png 3 +sketch/giraffe/n02439033_10802-1.png 3 +sketch/giraffe/n02439033_10802-2.png 3 +sketch/giraffe/n02439033_10802-3.png 3 +sketch/giraffe/n02439033_10802-4.png 3 +sketch/giraffe/n02439033_10802-5.png 3 +sketch/giraffe/n02439033_10802-6.png 3 +sketch/giraffe/n02439033_10802-7.png 3 +sketch/giraffe/n02439033_10802-8.png 3 +sketch/giraffe/n02439033_10803-1.png 3 +sketch/giraffe/n02439033_10803-2.png 3 +sketch/giraffe/n02439033_10803-3.png 3 +sketch/giraffe/n02439033_10803-4.png 3 +sketch/giraffe/n02439033_10803-5.png 3 +sketch/giraffe/n02439033_10811-1.png 3 +sketch/giraffe/n02439033_10811-2.png 3 +sketch/giraffe/n02439033_10811-3.png 3 +sketch/giraffe/n02439033_10811-4.png 3 +sketch/giraffe/n02439033_10811-5.png 3 +sketch/giraffe/n02439033_10811-6.png 3 +sketch/giraffe/n02439033_10811-7.png 3 +sketch/giraffe/n02439033_10839-1.png 3 +sketch/giraffe/n02439033_10839-2.png 3 +sketch/giraffe/n02439033_10839-3.png 3 +sketch/giraffe/n02439033_10839-4.png 3 +sketch/giraffe/n02439033_10839-5.png 3 +sketch/giraffe/n02439033_10839-6.png 3 +sketch/giraffe/n02439033_10839-7.png 3 +sketch/giraffe/n02439033_10919-1.png 3 +sketch/giraffe/n02439033_10919-2.png 3 +sketch/giraffe/n02439033_10919-3.png 3 +sketch/giraffe/n02439033_10919-4.png 3 +sketch/giraffe/n02439033_10919-5.png 3 +sketch/giraffe/n02439033_10919-6.png 3 +sketch/giraffe/n02439033_11059-1.png 3 +sketch/giraffe/n02439033_11059-2.png 3 +sketch/giraffe/n02439033_11059-3.png 3 +sketch/giraffe/n02439033_11059-4.png 3 +sketch/giraffe/n02439033_11059-5.png 3 +sketch/giraffe/n02439033_11059-6.png 3 +sketch/giraffe/n02439033_11059-7.png 3 +sketch/giraffe/n02439033_11059-8.png 3 +sketch/giraffe/n02439033_11059-9.png 3 +sketch/giraffe/n02439033_11114-1.png 3 +sketch/giraffe/n02439033_11114-2.png 3 +sketch/giraffe/n02439033_11114-3.png 3 +sketch/giraffe/n02439033_11114-4.png 3 +sketch/giraffe/n02439033_11114-5.png 3 +sketch/giraffe/n02439033_11130-1.png 3 +sketch/giraffe/n02439033_11130-2.png 3 +sketch/giraffe/n02439033_11130-3.png 3 +sketch/giraffe/n02439033_11130-4.png 3 +sketch/giraffe/n02439033_11130-5.png 3 +sketch/giraffe/n02439033_11130-6.png 3 +sketch/giraffe/n02439033_11215-1.png 3 +sketch/giraffe/n02439033_11215-2.png 3 +sketch/giraffe/n02439033_11215-3.png 3 +sketch/giraffe/n02439033_11215-4.png 3 +sketch/giraffe/n02439033_11215-5.png 3 +sketch/giraffe/n02439033_11273-1.png 3 +sketch/giraffe/n02439033_11273-2.png 3 +sketch/giraffe/n02439033_11273-3.png 3 +sketch/giraffe/n02439033_11273-4.png 3 +sketch/giraffe/n02439033_11273-5.png 3 +sketch/giraffe/n02439033_11273-6.png 3 +sketch/giraffe/n02439033_11328-1.png 3 +sketch/giraffe/n02439033_11328-2.png 3 +sketch/giraffe/n02439033_11328-3.png 3 +sketch/giraffe/n02439033_11328-4.png 3 +sketch/giraffe/n02439033_11328-5.png 3 +sketch/giraffe/n02439033_11328-6.png 3 +sketch/giraffe/n02439033_11458-1.png 3 +sketch/giraffe/n02439033_11458-2.png 3 +sketch/giraffe/n02439033_11458-3.png 3 +sketch/giraffe/n02439033_11458-4.png 3 +sketch/giraffe/n02439033_11458-5.png 3 +sketch/giraffe/n02439033_11458-6.png 3 +sketch/giraffe/n02439033_11486-1.png 3 +sketch/giraffe/n02439033_11486-2.png 3 +sketch/giraffe/n02439033_11486-3.png 3 +sketch/giraffe/n02439033_11486-4.png 3 +sketch/giraffe/n02439033_11486-5.png 3 +sketch/giraffe/n02439033_11487-1.png 3 +sketch/giraffe/n02439033_11487-2.png 3 +sketch/giraffe/n02439033_11487-3.png 3 +sketch/giraffe/n02439033_11487-4.png 3 +sketch/giraffe/n02439033_11487-5.png 3 +sketch/giraffe/n02439033_11487-6.png 3 +sketch/giraffe/n02439033_11487-7.png 3 +sketch/giraffe/n02439033_11504-1.png 3 +sketch/giraffe/n02439033_11504-2.png 3 +sketch/giraffe/n02439033_11504-3.png 3 +sketch/giraffe/n02439033_11504-4.png 3 +sketch/giraffe/n02439033_11504-5.png 3 +sketch/giraffe/n02439033_11504-6.png 3 +sketch/giraffe/n02439033_11504-7.png 3 +sketch/giraffe/n02439033_11599-1.png 3 +sketch/giraffe/n02439033_11599-2.png 3 +sketch/giraffe/n02439033_11599-3.png 3 +sketch/giraffe/n02439033_11599-4.png 3 +sketch/giraffe/n02439033_11599-5.png 3 +sketch/giraffe/n02439033_11599-6.png 3 +sketch/giraffe/n02439033_11599-7.png 3 +sketch/giraffe/n02439033_11599-8.png 3 +sketch/giraffe/n02439033_11627-1.png 3 +sketch/giraffe/n02439033_11627-2.png 3 +sketch/giraffe/n02439033_11627-3.png 3 +sketch/giraffe/n02439033_11627-4.png 3 +sketch/giraffe/n02439033_11627-5.png 3 +sketch/giraffe/n02439033_11627-6.png 3 +sketch/giraffe/n02439033_11627-7.png 3 +sketch/giraffe/n02439033_11666-1.png 3 +sketch/giraffe/n02439033_11666-2.png 3 +sketch/giraffe/n02439033_11666-3.png 3 +sketch/giraffe/n02439033_11666-4.png 3 +sketch/giraffe/n02439033_11666-5.png 3 +sketch/giraffe/n02439033_11666-6.png 3 +sketch/giraffe/n02439033_11666-7.png 3 +sketch/giraffe/n02439033_11683-1.png 3 +sketch/giraffe/n02439033_11683-2.png 3 +sketch/giraffe/n02439033_11683-3.png 3 +sketch/giraffe/n02439033_11683-4.png 3 +sketch/giraffe/n02439033_11683-5.png 3 +sketch/giraffe/n02439033_11683-6.png 3 +sketch/giraffe/n02439033_11683-7.png 3 +sketch/giraffe/n02439033_11715-1.png 3 +sketch/giraffe/n02439033_11715-2.png 3 +sketch/giraffe/n02439033_11715-3.png 3 +sketch/giraffe/n02439033_11715-4.png 3 +sketch/giraffe/n02439033_11715-5.png 3 +sketch/giraffe/n02439033_11715-6.png 3 +sketch/giraffe/n02439033_11845-1.png 3 +sketch/giraffe/n02439033_11845-2.png 3 +sketch/giraffe/n02439033_11845-3.png 3 +sketch/giraffe/n02439033_11845-4.png 3 +sketch/giraffe/n02439033_11845-5.png 3 +sketch/giraffe/n02439033_11845-6.png 3 +sketch/giraffe/n02439033_11845-7.png 3 +sketch/giraffe/n02439033_11845-8.png 3 +sketch/giraffe/n02439033_11845-9.png 3 +sketch/giraffe/n02439033_11845-10.png 3 +sketch/giraffe/n02439033_11894-1.png 3 +sketch/giraffe/n02439033_11894-2.png 3 +sketch/giraffe/n02439033_11894-3.png 3 +sketch/giraffe/n02439033_11894-4.png 3 +sketch/giraffe/n02439033_11894-5.png 3 +sketch/giraffe/n02439033_11894-6.png 3 +sketch/giraffe/n02439033_11894-7.png 3 +sketch/giraffe/n02439033_11894-8.png 3 +sketch/giraffe/n02439033_11894-9.png 3 +sketch/giraffe/n02439033_12059-1.png 3 +sketch/giraffe/n02439033_12059-2.png 3 +sketch/giraffe/n02439033_12059-3.png 3 +sketch/giraffe/n02439033_12059-4.png 3 +sketch/giraffe/n02439033_12059-5.png 3 +sketch/giraffe/n02439033_12413-1.png 3 +sketch/giraffe/n02439033_12413-2.png 3 +sketch/giraffe/n02439033_12413-3.png 3 +sketch/giraffe/n02439033_12413-4.png 3 +sketch/giraffe/n02439033_12413-5.png 3 +sketch/giraffe/n02439033_12413-6.png 3 +sketch/giraffe/n02439033_12413-7.png 3 +sketch/giraffe/n02439033_12485-1.png 3 +sketch/giraffe/n02439033_12485-2.png 3 +sketch/giraffe/n02439033_12485-3.png 3 +sketch/giraffe/n02439033_12485-4.png 3 +sketch/giraffe/n02439033_12485-5.png 3 +sketch/giraffe/n02439033_12485-6.png 3 +sketch/giraffe/n02439033_12680-1.png 3 +sketch/giraffe/n02439033_12680-2.png 3 +sketch/giraffe/n02439033_12680-3.png 3 +sketch/giraffe/n02439033_12680-4.png 3 +sketch/giraffe/n02439033_12680-5.png 3 +sketch/giraffe/n02439033_12930-1.png 3 +sketch/giraffe/n02439033_12930-2.png 3 +sketch/giraffe/n02439033_12930-3.png 3 +sketch/giraffe/n02439033_12930-4.png 3 +sketch/giraffe/n02439033_12930-5.png 3 +sketch/giraffe/n02439033_12939-1.png 3 +sketch/giraffe/n02439033_12939-2.png 3 +sketch/giraffe/n02439033_12939-3.png 3 +sketch/giraffe/n02439033_12939-4.png 3 +sketch/giraffe/n02439033_12939-5.png 3 +sketch/giraffe/n02439033_12939-6.png 3 +sketch/giraffe/n02439033_12939-7.png 3 +sketch/giraffe/n02439033_12939-8.png 3 +sketch/giraffe/n02439033_12987-1.png 3 +sketch/giraffe/n02439033_12987-2.png 3 +sketch/giraffe/n02439033_12987-3.png 3 +sketch/giraffe/n02439033_12987-4.png 3 +sketch/giraffe/n02439033_12987-5.png 3 +sketch/giraffe/n02439033_12987-6.png 3 +sketch/giraffe/n02439033_13236-1.png 3 +sketch/giraffe/n02439033_13236-2.png 3 +sketch/giraffe/n02439033_13236-3.png 3 +sketch/giraffe/n02439033_13236-4.png 3 +sketch/giraffe/n02439033_13236-5.png 3 +sketch/giraffe/n02439033_13236-6.png 3 +sketch/giraffe/n02439033_13384-1.png 3 +sketch/giraffe/n02439033_13384-2.png 3 +sketch/giraffe/n02439033_13384-3.png 3 +sketch/giraffe/n02439033_13384-4.png 3 +sketch/giraffe/n02439033_13384-5.png 3 +sketch/giraffe/n02439033_13384-6.png 3 +sketch/giraffe/n02439033_13430-1.png 3 +sketch/giraffe/n02439033_13430-2.png 3 +sketch/giraffe/n02439033_13430-3.png 3 +sketch/giraffe/n02439033_13430-4.png 3 +sketch/giraffe/n02439033_13430-5.png 3 +sketch/giraffe/n02439033_13602-1.png 3 +sketch/giraffe/n02439033_13602-2.png 3 +sketch/giraffe/n02439033_13602-3.png 3 +sketch/giraffe/n02439033_13602-4.png 3 +sketch/giraffe/n02439033_13602-5.png 3 +sketch/giraffe/n02439033_13602-6.png 3 +sketch/giraffe/n02439033_13602-7.png 3 +sketch/giraffe/n02439033_13868-1.png 3 +sketch/giraffe/n02439033_13868-2.png 3 +sketch/giraffe/n02439033_13868-3.png 3 +sketch/giraffe/n02439033_13868-4.png 3 +sketch/giraffe/n02439033_13868-5.png 3 +sketch/giraffe/n02439033_13868-6.png 3 +sketch/giraffe/n02439033_13868-7.png 3 +sketch/giraffe/n02439033_14040-1.png 3 +sketch/giraffe/n02439033_14040-2.png 3 +sketch/giraffe/n02439033_14040-3.png 3 +sketch/giraffe/n02439033_14040-4.png 3 +sketch/giraffe/n02439033_14040-5.png 3 +sketch/giraffe/n02439033_14040-6.png 3 +sketch/giraffe/n02439033_14060-1.png 3 +sketch/giraffe/n02439033_14060-2.png 3 +sketch/giraffe/n02439033_14060-3.png 3 +sketch/giraffe/n02439033_14060-4.png 3 +sketch/giraffe/n02439033_14060-5.png 3 +sketch/giraffe/n02439033_14060-6.png 3 +sketch/giraffe/n02439033_14060-7.png 3 +sketch/giraffe/n02439033_14060-8.png 3 +sketch/giraffe/n02439033_14121-1.png 3 +sketch/giraffe/n02439033_14121-2.png 3 +sketch/giraffe/n02439033_14121-3.png 3 +sketch/giraffe/n02439033_14121-4.png 3 +sketch/giraffe/n02439033_14121-5.png 3 +sketch/giraffe/n02439033_14121-6.png 3 +sketch/giraffe/n02439033_14121-7.png 3 +sketch/giraffe/n02439033_14121-8.png 3 +sketch/giraffe/n02439033_14121-9.png 3 +sketch/giraffe/n02439033_14121-10.png 3 +sketch/giraffe/n02439033_14148-1.png 3 +sketch/giraffe/n02439033_14148-2.png 3 +sketch/giraffe/n02439033_14148-3.png 3 +sketch/giraffe/n02439033_14148-4.png 3 +sketch/giraffe/n02439033_14148-5.png 3 +sketch/giraffe/n02439033_14148-6.png 3 +sketch/giraffe/n02439033_14148-7.png 3 +sketch/giraffe/n02439033_14148-8.png 3 +sketch/giraffe/n02439033_14148-9.png 3 +sketch/giraffe/n02439033_14148-10.png 3 +sketch/giraffe/n02439033_14184-1.png 3 +sketch/giraffe/n02439033_14184-2.png 3 +sketch/giraffe/n02439033_14184-3.png 3 +sketch/giraffe/7361.png 3 +sketch/giraffe/n02439033_14184-4.png 3 +sketch/giraffe/n02439033_14184-5.png 3 +sketch/giraffe/n02439033_14322-1.png 3 +sketch/giraffe/n02439033_14322-2.png 3 +sketch/giraffe/n02439033_14322-3.png 3 +sketch/giraffe/n02439033_14322-4.png 3 +sketch/giraffe/n02439033_14322-5.png 3 +sketch/giraffe/n02439033_14497-1.png 3 +sketch/giraffe/n02439033_14497-2.png 3 +sketch/giraffe/n02439033_14497-3.png 3 +sketch/giraffe/n02439033_14497-4.png 3 +sketch/giraffe/n02439033_14497-5.png 3 +sketch/giraffe/n02439033_14497-6.png 3 +sketch/giraffe/n02439033_14554-1.png 3 +sketch/giraffe/n02439033_14554-2.png 3 +sketch/giraffe/n02439033_14554-3.png 3 +sketch/giraffe/n02439033_14554-4.png 3 +sketch/giraffe/n02439033_14554-5.png 3 +sketch/giraffe/n02439033_14554-6.png 3 +sketch/giraffe/n02439033_14554-7.png 3 +sketch/giraffe/n02439033_14554-8.png 3 +sketch/giraffe/n02439033_14554-9.png 3 +sketch/giraffe/n02439033_14580-1.png 3 +sketch/giraffe/n02439033_14580-2.png 3 +sketch/giraffe/n02439033_14580-3.png 3 +sketch/giraffe/n02439033_14580-4.png 3 +sketch/giraffe/n02439033_14580-5.png 3 +sketch/giraffe/n02439033_14580-6.png 3 +sketch/giraffe/n02439033_14580-7.png 3 +sketch/giraffe/n02439033_14580-8.png 3 +sketch/giraffe/n02439033_14580-9.png 3 +sketch/giraffe/n02439033_14580-10.png 3 +sketch/giraffe/n02439033_14600-1.png 3 +sketch/giraffe/n02439033_14600-2.png 3 +sketch/giraffe/n02439033_14600-3.png 3 +sketch/giraffe/n02439033_14600-4.png 3 +sketch/giraffe/n02439033_14600-5.png 3 +sketch/giraffe/n02439033_14600-6.png 3 +sketch/giraffe/n02439033_14600-7.png 3 +sketch/giraffe/n02439033_14600-8.png 3 +sketch/giraffe/n02439033_14600-9.png 3 +sketch/giraffe/n02439033_14609-1.png 3 +sketch/giraffe/n02439033_14609-2.png 3 +sketch/giraffe/n02439033_14609-3.png 3 +sketch/giraffe/n02439033_14609-4.png 3 +sketch/giraffe/n02439033_14609-5.png 3 +sketch/giraffe/n02439033_14609-6.png 3 +sketch/giraffe/n02439033_14724-1.png 3 +sketch/giraffe/n02439033_14724-2.png 3 +sketch/giraffe/n02439033_14724-3.png 3 +sketch/giraffe/n02439033_14724-4.png 3 +sketch/giraffe/n02439033_14724-5.png 3 +sketch/giraffe/n02439033_14764-1.png 3 +sketch/giraffe/n02439033_14764-2.png 3 +sketch/giraffe/n02439033_14764-3.png 3 +sketch/giraffe/n02439033_14764-4.png 3 +sketch/giraffe/n02439033_14764-5.png 3 +sketch/giraffe/n02439033_14781-1.png 3 +sketch/giraffe/n02439033_14781-2.png 3 +sketch/giraffe/n02439033_14781-3.png 3 +sketch/giraffe/n02439033_14781-4.png 3 +sketch/giraffe/n02439033_14781-5.png 3 +sketch/giraffe/n02439033_14781-6.png 3 +sketch/giraffe/n02439033_14781-7.png 3 +sketch/giraffe/n02439033_14781-8.png 3 +sketch/giraffe/n02439033_14784-1.png 3 +sketch/giraffe/n02439033_14784-2.png 3 +sketch/giraffe/n02439033_14784-3.png 3 +sketch/giraffe/n02439033_14784-4.png 3 +sketch/giraffe/n02439033_14784-5.png 3 +sketch/giraffe/n02439033_14784-6.png 3 +sketch/giraffe/n02439033_14846-1.png 3 +sketch/giraffe/n02439033_14846-2.png 3 +sketch/giraffe/n02439033_14846-3.png 3 +sketch/giraffe/n02439033_14846-4.png 3 +sketch/giraffe/n02439033_14846-5.png 3 +sketch/giraffe/n02439033_14846-6.png 3 +sketch/giraffe/n02439033_14846-7.png 3 +sketch/giraffe/n02439033_14846-8.png 3 +sketch/giraffe/n02439033_14872-1.png 3 +sketch/giraffe/n02439033_14872-2.png 3 +sketch/giraffe/n02439033_14872-3.png 3 +sketch/giraffe/n02439033_14872-4.png 3 +sketch/giraffe/n02439033_14872-5.png 3 +sketch/giraffe/n02439033_14872-6.png 3 +sketch/giraffe/n02439033_14885-1.png 3 +sketch/giraffe/n02439033_14885-2.png 3 +sketch/giraffe/n02439033_14885-3.png 3 +sketch/giraffe/n02439033_14885-4.png 3 +sketch/giraffe/n02439033_14885-5.png 3 +sketch/giraffe/n02439033_14962-1.png 3 +sketch/giraffe/n02439033_14962-2.png 3 +sketch/giraffe/n02439033_14962-3.png 3 +sketch/giraffe/n02439033_14962-4.png 3 +sketch/giraffe/n02439033_14962-5.png 3 +sketch/giraffe/n02439033_14962-6.png 3 +sketch/giraffe/n02439033_14962-7.png 3 +sketch/giraffe/n02439033_15005-1.png 3 +sketch/giraffe/n02439033_15005-2.png 3 +sketch/giraffe/n02439033_15005-3.png 3 +sketch/giraffe/n02439033_15005-4.png 3 +sketch/giraffe/n02439033_15005-5.png 3 +sketch/giraffe/n02439033_15005-6.png 3 +sketch/giraffe/n02439033_15005-7.png 3 +sketch/giraffe/n02439033_15005-8.png 3 +sketch/giraffe/n02439033_15005-9.png 3 +sketch/giraffe/n02439033_15005-10.png 3 +sketch/giraffe/n02439033_15384-1.png 3 +sketch/giraffe/n02439033_15384-2.png 3 +sketch/giraffe/n02439033_15384-3.png 3 +sketch/giraffe/n02439033_15384-4.png 3 +sketch/giraffe/n02439033_15384-5.png 3 +sketch/giraffe/n02439033_15401-1.png 3 +sketch/giraffe/n02439033_15401-2.png 3 +sketch/giraffe/n02439033_15401-3.png 3 +sketch/giraffe/n02439033_15401-4.png 3 +sketch/giraffe/n02439033_15401-5.png 3 +sketch/giraffe/n02439033_15453-1.png 3 +sketch/giraffe/n02439033_15453-2.png 3 +sketch/giraffe/n02439033_15453-3.png 3 +sketch/giraffe/n02439033_15453-4.png 3 +sketch/giraffe/n02439033_15453-5.png 3 +sketch/giraffe/n02439033_15453-6.png 3 +sketch/giraffe/n02439033_15453-7.png 3 +sketch/giraffe/n02439033_15453-8.png 3 +sketch/giraffe/n02439033_15453-9.png 3 +sketch/giraffe/n02439033_15479-1.png 3 +sketch/giraffe/n02439033_15479-2.png 3 +sketch/giraffe/n02439033_15479-3.png 3 +sketch/giraffe/n02439033_15479-4.png 3 +sketch/giraffe/n02439033_15479-5.png 3 +sketch/giraffe/n02439033_15479-6.png 3 +sketch/giraffe/n02439033_15479-7.png 3 +sketch/giraffe/n02439033_15540-1.png 3 +sketch/giraffe/n02439033_15540-2.png 3 +sketch/giraffe/n02439033_15540-3.png 3 +sketch/giraffe/n02439033_15540-4.png 3 +sketch/giraffe/n02439033_15540-5.png 3 +sketch/giraffe/n02439033_15540-6.png 3 +sketch/giraffe/n02439033_15555-1.png 3 +sketch/giraffe/n02439033_15555-2.png 3 +sketch/giraffe/n02439033_15555-3.png 3 +sketch/giraffe/n02439033_15555-4.png 3 +sketch/giraffe/n02439033_15555-5.png 3 +sketch/giraffe/n02439033_15936-1.png 3 +sketch/giraffe/n02439033_15936-2.png 3 +sketch/giraffe/n02439033_15936-3.png 3 +sketch/giraffe/n02439033_15936-4.png 3 +sketch/giraffe/n02439033_15936-5.png 3 +sketch/giraffe/n02439033_15936-6.png 3 +sketch/giraffe/n02439033_15936-7.png 3 +sketch/giraffe/n02439033_16085-1.png 3 +sketch/giraffe/n02439033_16085-2.png 3 +sketch/giraffe/n02439033_16085-3.png 3 +sketch/giraffe/n02439033_16085-4.png 3 +sketch/giraffe/n02439033_16085-5.png 3 +sketch/giraffe/n02439033_16356-1.png 3 +sketch/giraffe/n02439033_16356-2.png 3 +sketch/giraffe/n02439033_16356-3.png 3 +sketch/giraffe/n02439033_16356-4.png 3 +sketch/giraffe/n02439033_16356-5.png 3 +sketch/giraffe/n02439033_16483-1.png 3 +sketch/giraffe/n02439033_16483-2.png 3 +sketch/giraffe/n02439033_16483-3.png 3 +sketch/giraffe/n02439033_16483-4.png 3 +sketch/giraffe/n02439033_16483-5.png 3 +sketch/giraffe/n02439033_16483-6.png 3 +sketch/giraffe/7362.png 3 +sketch/giraffe/7363.png 3 +sketch/giraffe/7364.png 3 +sketch/giraffe/7365.png 3 +sketch/giraffe/7366.png 3 +sketch/giraffe/7367.png 3 +sketch/giraffe/7368.png 3 +sketch/giraffe/7369.png 3 +sketch/giraffe/7370.png 3 +sketch/giraffe/7371.png 3 +sketch/giraffe/7372.png 3 +sketch/giraffe/7373.png 3 +sketch/giraffe/7374.png 3 +sketch/giraffe/7375.png 3 +sketch/giraffe/7376.png 3 +sketch/giraffe/7377.png 3 +sketch/giraffe/7378.png 3 +sketch/giraffe/7379.png 3 +sketch/giraffe/7380.png 3 +sketch/giraffe/7381.png 3 +sketch/giraffe/7382.png 3 +sketch/giraffe/7383.png 3 +sketch/giraffe/7384.png 3 +sketch/giraffe/7385.png 3 +sketch/giraffe/7386.png 3 +sketch/giraffe/7387.png 3 +sketch/giraffe/7388.png 3 +sketch/giraffe/7389.png 3 +sketch/giraffe/7390.png 3 +sketch/giraffe/7391.png 3 +sketch/giraffe/7392.png 3 +sketch/giraffe/7393.png 3 +sketch/giraffe/7394.png 3 +sketch/giraffe/7395.png 3 +sketch/giraffe/7396.png 3 +sketch/giraffe/7397.png 3 +sketch/giraffe/7398.png 3 +sketch/giraffe/7399.png 3 +sketch/giraffe/7400.png 3 +sketch/giraffe/7401.png 3 +sketch/giraffe/7402.png 3 +sketch/giraffe/7403.png 3 +sketch/giraffe/7404.png 3 +sketch/giraffe/7405.png 3 +sketch/giraffe/7406.png 3 +sketch/giraffe/7407.png 3 +sketch/giraffe/7408.png 3 +sketch/giraffe/7409.png 3 +sketch/giraffe/7410.png 3 +sketch/giraffe/7411.png 3 +sketch/giraffe/7412.png 3 +sketch/giraffe/7413.png 3 +sketch/giraffe/7414.png 3 +sketch/giraffe/7415.png 3 +sketch/giraffe/7416.png 3 +sketch/giraffe/7417.png 3 +sketch/giraffe/7418.png 3 +sketch/giraffe/7419.png 3 +sketch/giraffe/7420.png 3 +sketch/giraffe/7421.png 3 +sketch/giraffe/7422.png 3 +sketch/giraffe/7423.png 3 +sketch/giraffe/7424.png 3 +sketch/giraffe/7425.png 3 +sketch/giraffe/7426.png 3 +sketch/giraffe/7427.png 3 +sketch/giraffe/7428.png 3 +sketch/giraffe/7429.png 3 +sketch/giraffe/7430.png 3 +sketch/giraffe/7431.png 3 +sketch/giraffe/7432.png 3 +sketch/giraffe/7433.png 3 +sketch/giraffe/7434.png 3 +sketch/giraffe/7435.png 3 +sketch/giraffe/7436.png 3 +sketch/giraffe/7437.png 3 +sketch/giraffe/7438.png 3 +sketch/giraffe/7439.png 3 +sketch/giraffe/7440.png 3 +sketch/guitar/7601.png 4 +sketch/guitar/7602.png 4 +sketch/guitar/7603.png 4 +sketch/guitar/7604.png 4 +sketch/guitar/7605.png 4 +sketch/guitar/7606.png 4 +sketch/guitar/7607.png 4 +sketch/guitar/7608.png 4 +sketch/guitar/7609.png 4 +sketch/guitar/7610.png 4 +sketch/guitar/7611.png 4 +sketch/guitar/7612.png 4 +sketch/guitar/7613.png 4 +sketch/guitar/7614.png 4 +sketch/guitar/7615.png 4 +sketch/guitar/7616.png 4 +sketch/guitar/7617.png 4 +sketch/guitar/7618.png 4 +sketch/guitar/7619.png 4 +sketch/guitar/7620.png 4 +sketch/guitar/7621.png 4 +sketch/guitar/7622.png 4 +sketch/guitar/7623.png 4 +sketch/guitar/7624.png 4 +sketch/guitar/7625.png 4 +sketch/guitar/7626.png 4 +sketch/guitar/7627.png 4 +sketch/guitar/7628.png 4 +sketch/guitar/7629.png 4 +sketch/guitar/7630.png 4 +sketch/guitar/7631.png 4 +sketch/guitar/7632.png 4 +sketch/guitar/7633.png 4 +sketch/guitar/7634.png 4 +sketch/guitar/7635.png 4 +sketch/guitar/7636.png 4 +sketch/guitar/7637.png 4 +sketch/guitar/7638.png 4 +sketch/guitar/7639.png 4 +sketch/guitar/7640.png 4 +sketch/guitar/7641.png 4 +sketch/guitar/7642.png 4 +sketch/guitar/7643.png 4 +sketch/guitar/7644.png 4 +sketch/guitar/7645.png 4 +sketch/guitar/7646.png 4 +sketch/guitar/7647.png 4 +sketch/guitar/7648.png 4 +sketch/guitar/7649.png 4 +sketch/guitar/7650.png 4 +sketch/guitar/7651.png 4 +sketch/guitar/7652.png 4 +sketch/guitar/7653.png 4 +sketch/guitar/7654.png 4 +sketch/guitar/7655.png 4 +sketch/guitar/7656.png 4 +sketch/guitar/7657.png 4 +sketch/guitar/7658.png 4 +sketch/guitar/7659.png 4 +sketch/guitar/7660.png 4 +sketch/guitar/7661.png 4 +sketch/guitar/7662.png 4 +sketch/guitar/7663.png 4 +sketch/guitar/7664.png 4 +sketch/guitar/7665.png 4 +sketch/guitar/7666.png 4 +sketch/guitar/7667.png 4 +sketch/guitar/7668.png 4 +sketch/guitar/7669.png 4 +sketch/guitar/7670.png 4 +sketch/guitar/7671.png 4 +sketch/guitar/7672.png 4 +sketch/guitar/7673.png 4 +sketch/guitar/7674.png 4 +sketch/guitar/7675.png 4 +sketch/guitar/7676.png 4 +sketch/guitar/7677.png 4 +sketch/guitar/7678.png 4 +sketch/guitar/7679.png 4 +sketch/guitar/7680.png 4 +sketch/guitar/n02676566_307-1.png 4 +sketch/guitar/n02676566_307-2.png 4 +sketch/guitar/n02676566_307-3.png 4 +sketch/guitar/n02676566_307-4.png 4 +sketch/guitar/n02676566_307-5.png 4 +sketch/guitar/n02676566_330-1.png 4 +sketch/guitar/n02676566_330-2.png 4 +sketch/guitar/n02676566_330-3.png 4 +sketch/guitar/n02676566_330-4.png 4 +sketch/guitar/n02676566_330-5.png 4 +sketch/guitar/n02676566_330-6.png 4 +sketch/guitar/n02676566_659-1.png 4 +sketch/guitar/n02676566_659-2.png 4 +sketch/guitar/n02676566_659-3.png 4 +sketch/guitar/n02676566_659-4.png 4 +sketch/guitar/n02676566_659-5.png 4 +sketch/guitar/n02676566_970-1.png 4 +sketch/guitar/n02676566_970-2.png 4 +sketch/guitar/n02676566_970-3.png 4 +sketch/guitar/n02676566_970-4.png 4 +sketch/guitar/n02676566_970-5.png 4 +sketch/guitar/n02676566_970-6.png 4 +sketch/guitar/n02676566_1324-1.png 4 +sketch/guitar/n02676566_1324-2.png 4 +sketch/guitar/n02676566_1324-3.png 4 +sketch/guitar/n02676566_1324-4.png 4 +sketch/guitar/n02676566_1324-5.png 4 +sketch/guitar/n02676566_2380-1.png 4 +sketch/guitar/n02676566_2380-2.png 4 +sketch/guitar/n02676566_2380-3.png 4 +sketch/guitar/n02676566_2380-4.png 4 +sketch/guitar/n02676566_2380-5.png 4 +sketch/guitar/n02676566_2866-1.png 4 +sketch/guitar/n02676566_2866-2.png 4 +sketch/guitar/n02676566_2866-3.png 4 +sketch/guitar/n02676566_2866-4.png 4 +sketch/guitar/n02676566_2866-5.png 4 +sketch/guitar/n02676566_3360-1.png 4 +sketch/guitar/n02676566_3360-2.png 4 +sketch/guitar/n02676566_3360-3.png 4 +sketch/guitar/n02676566_3360-4.png 4 +sketch/guitar/n02676566_3360-5.png 4 +sketch/guitar/n02676566_3360-6.png 4 +sketch/guitar/n02676566_4058-1.png 4 +sketch/guitar/n02676566_4058-2.png 4 +sketch/guitar/n02676566_4058-3.png 4 +sketch/guitar/n02676566_4058-4.png 4 +sketch/guitar/n02676566_4058-5.png 4 +sketch/guitar/n02676566_4058-6.png 4 +sketch/guitar/n02676566_4189-1.png 4 +sketch/guitar/n02676566_4189-2.png 4 +sketch/guitar/n02676566_4189-3.png 4 +sketch/guitar/n02676566_4189-4.png 4 +sketch/guitar/n02676566_4189-5.png 4 +sketch/guitar/n02676566_4469-1.png 4 +sketch/guitar/n02676566_4469-2.png 4 +sketch/guitar/n02676566_4469-3.png 4 +sketch/guitar/n02676566_4469-4.png 4 +sketch/guitar/n02676566_4469-5.png 4 +sketch/guitar/n02676566_4605-1.png 4 +sketch/guitar/n02676566_4605-2.png 4 +sketch/guitar/n02676566_4605-3.png 4 +sketch/guitar/n02676566_4605-4.png 4 +sketch/guitar/n02676566_4605-5.png 4 +sketch/guitar/n02676566_4605-6.png 4 +sketch/guitar/n02676566_4699-1.png 4 +sketch/guitar/n02676566_4699-2.png 4 +sketch/guitar/n02676566_4699-3.png 4 +sketch/guitar/n02676566_4699-4.png 4 +sketch/guitar/n02676566_4699-5.png 4 +sketch/guitar/n02676566_5134-1.png 4 +sketch/guitar/n02676566_5134-2.png 4 +sketch/guitar/n02676566_5134-3.png 4 +sketch/guitar/n02676566_5134-4.png 4 +sketch/guitar/n02676566_5134-5.png 4 +sketch/guitar/n02676566_5489-1.png 4 +sketch/guitar/n02676566_5489-2.png 4 +sketch/guitar/n02676566_5489-3.png 4 +sketch/guitar/n02676566_5489-4.png 4 +sketch/guitar/n02676566_5489-5.png 4 +sketch/guitar/n02676566_5489-6.png 4 +sketch/guitar/n02676566_5489-7.png 4 +sketch/guitar/n02676566_5735-1.png 4 +sketch/guitar/n02676566_5735-2.png 4 +sketch/guitar/n02676566_5735-3.png 4 +sketch/guitar/n02676566_5735-4.png 4 +sketch/guitar/n02676566_5735-5.png 4 +sketch/guitar/n02676566_6150-1.png 4 +sketch/guitar/n02676566_6150-2.png 4 +sketch/guitar/n02676566_6150-3.png 4 +sketch/guitar/n02676566_6150-4.png 4 +sketch/guitar/n02676566_6150-5.png 4 +sketch/guitar/n02676566_6402-1.png 4 +sketch/guitar/n02676566_6402-2.png 4 +sketch/guitar/n02676566_6402-3.png 4 +sketch/guitar/n02676566_6402-4.png 4 +sketch/guitar/n02676566_6402-5.png 4 +sketch/guitar/n02676566_6430-1.png 4 +sketch/guitar/n02676566_6430-2.png 4 +sketch/guitar/n02676566_6430-3.png 4 +sketch/guitar/n02676566_6430-4.png 4 +sketch/guitar/n02676566_6430-5.png 4 +sketch/guitar/n02676566_6560-1.png 4 +sketch/guitar/n02676566_6560-2.png 4 +sketch/guitar/n02676566_6560-3.png 4 +sketch/guitar/n02676566_6560-4.png 4 +sketch/guitar/n02676566_6560-5.png 4 +sketch/guitar/n02676566_6631-1.png 4 +sketch/guitar/n02676566_6631-2.png 4 +sketch/guitar/n02676566_6631-3.png 4 +sketch/guitar/n02676566_6631-4.png 4 +sketch/guitar/n02676566_6631-5.png 4 +sketch/guitar/n02676566_6704-1.png 4 +sketch/guitar/n02676566_6704-2.png 4 +sketch/guitar/n02676566_6704-3.png 4 +sketch/guitar/n02676566_6704-4.png 4 +sketch/guitar/n02676566_6704-5.png 4 +sketch/guitar/n02676566_6864-1.png 4 +sketch/guitar/n02676566_6864-2.png 4 +sketch/guitar/n02676566_6864-3.png 4 +sketch/guitar/n02676566_6864-4.png 4 +sketch/guitar/n02676566_6864-5.png 4 +sketch/guitar/n02676566_6914-1.png 4 +sketch/guitar/n02676566_6914-2.png 4 +sketch/guitar/n02676566_6914-3.png 4 +sketch/guitar/n02676566_6914-4.png 4 +sketch/guitar/n02676566_6914-5.png 4 +sketch/guitar/n02676566_6948-1.png 4 +sketch/guitar/n02676566_6948-2.png 4 +sketch/guitar/n02676566_6948-3.png 4 +sketch/guitar/n02676566_6948-4.png 4 +sketch/guitar/n02676566_6948-5.png 4 +sketch/guitar/n02676566_6980-1.png 4 +sketch/guitar/n02676566_6980-2.png 4 +sketch/guitar/n02676566_6980-3.png 4 +sketch/guitar/n02676566_6980-4.png 4 +sketch/guitar/n02676566_6980-5.png 4 +sketch/guitar/n02676566_7385-1.png 4 +sketch/guitar/n02676566_7385-2.png 4 +sketch/guitar/n02676566_7385-3.png 4 +sketch/guitar/n02676566_7385-4.png 4 +sketch/guitar/n02676566_7385-5.png 4 +sketch/guitar/n02676566_7385-6.png 4 +sketch/guitar/n02676566_7770-1.png 4 +sketch/guitar/n02676566_7770-2.png 4 +sketch/guitar/n02676566_7770-3.png 4 +sketch/guitar/n02676566_7770-4.png 4 +sketch/guitar/n02676566_7770-5.png 4 +sketch/guitar/n02676566_7830-1.png 4 +sketch/guitar/n02676566_7830-2.png 4 +sketch/guitar/n02676566_7830-3.png 4 +sketch/guitar/n02676566_7830-4.png 4 +sketch/guitar/n02676566_7830-5.png 4 +sketch/guitar/n02676566_7844-1.png 4 +sketch/guitar/n02676566_7844-2.png 4 +sketch/guitar/n02676566_7844-3.png 4 +sketch/guitar/n02676566_7844-4.png 4 +sketch/guitar/n02676566_7844-5.png 4 +sketch/guitar/n02676566_7927-1.png 4 +sketch/guitar/n02676566_7927-2.png 4 +sketch/guitar/n02676566_7927-3.png 4 +sketch/guitar/n02676566_7927-4.png 4 +sketch/guitar/n02676566_7927-5.png 4 +sketch/guitar/n02676566_7927-6.png 4 +sketch/guitar/n02676566_8268-1.png 4 +sketch/guitar/n02676566_8268-2.png 4 +sketch/guitar/n02676566_8268-3.png 4 +sketch/guitar/n02676566_8268-4.png 4 +sketch/guitar/n02676566_8268-5.png 4 +sketch/guitar/n02676566_8309-1.png 4 +sketch/guitar/n02676566_8309-2.png 4 +sketch/guitar/n02676566_8309-3.png 4 +sketch/guitar/n02676566_8309-4.png 4 +sketch/guitar/n02676566_8309-5.png 4 +sketch/guitar/n02676566_8467-1.png 4 +sketch/guitar/n02676566_8467-2.png 4 +sketch/guitar/n02676566_8467-3.png 4 +sketch/guitar/n02676566_8467-4.png 4 +sketch/guitar/n02676566_8467-5.png 4 +sketch/guitar/n02676566_8618-1.png 4 +sketch/guitar/n02676566_8618-2.png 4 +sketch/guitar/n02676566_8618-3.png 4 +sketch/guitar/n02676566_8618-4.png 4 +sketch/guitar/n02676566_8618-5.png 4 +sketch/guitar/n02676566_8618-6.png 4 +sketch/guitar/n02676566_8820-1.png 4 +sketch/guitar/n02676566_8820-2.png 4 +sketch/guitar/n02676566_8820-3.png 4 +sketch/guitar/n02676566_8820-4.png 4 +sketch/guitar/n02676566_8820-5.png 4 +sketch/guitar/n02676566_8859-1.png 4 +sketch/guitar/n02676566_8859-2.png 4 +sketch/guitar/n02676566_8859-3.png 4 +sketch/guitar/n02676566_8859-4.png 4 +sketch/guitar/n02676566_8859-5.png 4 +sketch/guitar/n02676566_8859-6.png 4 +sketch/guitar/n02676566_8997-1.png 4 +sketch/guitar/n02676566_8997-2.png 4 +sketch/guitar/n02676566_8997-3.png 4 +sketch/guitar/n02676566_8997-4.png 4 +sketch/guitar/n02676566_8997-5.png 4 +sketch/guitar/n02676566_9062-1.png 4 +sketch/guitar/n02676566_9062-2.png 4 +sketch/guitar/n02676566_9062-3.png 4 +sketch/guitar/n02676566_9062-4.png 4 +sketch/guitar/n02676566_9062-5.png 4 +sketch/guitar/n02676566_9243-1.png 4 +sketch/guitar/n02676566_9243-2.png 4 +sketch/guitar/n02676566_9243-3.png 4 +sketch/guitar/n02676566_9243-4.png 4 +sketch/guitar/n02676566_9243-5.png 4 +sketch/guitar/n02676566_9243-6.png 4 +sketch/guitar/n02676566_9254-1.png 4 +sketch/guitar/n02676566_9254-2.png 4 +sketch/guitar/n02676566_9254-3.png 4 +sketch/guitar/n02676566_9254-4.png 4 +sketch/guitar/n02676566_9254-5.png 4 +sketch/guitar/n02676566_9451-1.png 4 +sketch/guitar/n02676566_9451-2.png 4 +sketch/guitar/n02676566_9451-3.png 4 +sketch/guitar/n02676566_9451-4.png 4 +sketch/guitar/n02676566_9451-5.png 4 +sketch/guitar/n02676566_9577-1.png 4 +sketch/guitar/n02676566_9577-2.png 4 +sketch/guitar/n02676566_9577-3.png 4 +sketch/guitar/n02676566_9577-4.png 4 +sketch/guitar/n02676566_9577-5.png 4 +sketch/guitar/n02676566_9577-6.png 4 +sketch/guitar/n02676566_9612-1.png 4 +sketch/guitar/n02676566_9612-2.png 4 +sketch/guitar/n02676566_9612-3.png 4 +sketch/guitar/n02676566_9612-4.png 4 +sketch/guitar/n02676566_9612-5.png 4 +sketch/guitar/n02676566_9661-1.png 4 +sketch/guitar/n02676566_9661-2.png 4 +sketch/guitar/n02676566_9661-3.png 4 +sketch/guitar/n02676566_9661-4.png 4 +sketch/guitar/n02676566_9661-5.png 4 +sketch/guitar/n02676566_9661-6.png 4 +sketch/guitar/n02676566_9936-1.png 4 +sketch/guitar/n02676566_9936-2.png 4 +sketch/guitar/n02676566_9936-3.png 4 +sketch/guitar/n02676566_9936-4.png 4 +sketch/guitar/n02676566_9936-5.png 4 +sketch/guitar/n02676566_11377-1.png 4 +sketch/guitar/n02676566_11377-2.png 4 +sketch/guitar/n02676566_11377-3.png 4 +sketch/guitar/n02676566_11377-4.png 4 +sketch/guitar/n02676566_11377-5.png 4 +sketch/guitar/n02676566_11573-1.png 4 +sketch/guitar/n02676566_11573-2.png 4 +sketch/guitar/n02676566_11573-3.png 4 +sketch/guitar/n02676566_11573-4.png 4 +sketch/guitar/n02676566_11573-5.png 4 +sketch/guitar/n02676566_12344-1.png 4 +sketch/guitar/n02676566_12344-2.png 4 +sketch/guitar/n02676566_12344-3.png 4 +sketch/guitar/n02676566_12344-4.png 4 +sketch/guitar/n02676566_12344-5.png 4 +sketch/guitar/n03272010_392-1.png 4 +sketch/guitar/n03272010_392-2.png 4 +sketch/guitar/n03272010_392-3.png 4 +sketch/guitar/n03272010_392-4.png 4 +sketch/guitar/n03272010_392-5.png 4 +sketch/guitar/n03272010_446-1.png 4 +sketch/guitar/n03272010_446-2.png 4 +sketch/guitar/n03272010_446-3.png 4 +sketch/guitar/n03272010_446-4.png 4 +sketch/guitar/n03272010_446-5.png 4 +sketch/guitar/n03272010_1708-1.png 4 +sketch/guitar/n03272010_1708-2.png 4 +sketch/guitar/n03272010_1708-3.png 4 +sketch/guitar/n03272010_1708-4.png 4 +sketch/guitar/n03272010_1708-5.png 4 +sketch/guitar/n03272010_1708-6.png 4 +sketch/guitar/n03272010_3732-1.png 4 +sketch/guitar/n03272010_3732-2.png 4 +sketch/guitar/n03272010_3732-3.png 4 +sketch/guitar/n03272010_3732-4.png 4 +sketch/guitar/n03272010_3732-5.png 4 +sketch/guitar/n03272010_3732-6.png 4 +sketch/guitar/n03272010_5483-1.png 4 +sketch/guitar/n03272010_5483-2.png 4 +sketch/guitar/n03272010_5483-3.png 4 +sketch/guitar/n03272010_5483-4.png 4 +sketch/guitar/n03272010_5483-5.png 4 +sketch/guitar/n03272010_5483-6.png 4 +sketch/guitar/n03272010_5875-1.png 4 +sketch/guitar/n03272010_5875-2.png 4 +sketch/guitar/n03272010_5875-3.png 4 +sketch/guitar/n03272010_5875-4.png 4 +sketch/guitar/n03272010_5875-5.png 4 +sketch/guitar/n03272010_5887-1.png 4 +sketch/guitar/n03272010_5887-2.png 4 +sketch/guitar/n03272010_5887-3.png 4 +sketch/guitar/n03272010_5887-4.png 4 +sketch/guitar/n03272010_5887-5.png 4 +sketch/guitar/n03272010_5887-6.png 4 +sketch/guitar/n03272010_5887-7.png 4 +sketch/guitar/n03272010_6152-1.png 4 +sketch/guitar/n03272010_6152-2.png 4 +sketch/guitar/n03272010_6152-3.png 4 +sketch/guitar/n03272010_6152-4.png 4 +sketch/guitar/n03272010_6152-5.png 4 +sketch/guitar/n03272010_6255-1.png 4 +sketch/guitar/n03272010_6255-2.png 4 +sketch/guitar/n03272010_6255-3.png 4 +sketch/guitar/n03272010_6255-4.png 4 +sketch/guitar/n03272010_6255-5.png 4 +sketch/guitar/n03272010_6291-1.png 4 +sketch/guitar/n03272010_6291-2.png 4 +sketch/guitar/n03272010_6291-3.png 4 +sketch/guitar/n03272010_6291-4.png 4 +sketch/guitar/n03272010_6291-5.png 4 +sketch/guitar/n03272010_6650-1.png 4 +sketch/guitar/n03272010_6650-2.png 4 +sketch/guitar/n03272010_6650-3.png 4 +sketch/guitar/n03272010_6650-4.png 4 +sketch/guitar/n03272010_6650-5.png 4 +sketch/guitar/n03272010_6650-6.png 4 +sketch/guitar/n03272010_6662-1.png 4 +sketch/guitar/n03272010_6662-2.png 4 +sketch/guitar/n03272010_6662-3.png 4 +sketch/guitar/n03272010_6662-4.png 4 +sketch/guitar/n03272010_6662-5.png 4 +sketch/guitar/n03272010_6662-6.png 4 +sketch/guitar/n03272010_6662-7.png 4 +sketch/guitar/n03272010_6718-1.png 4 +sketch/guitar/n03272010_6718-2.png 4 +sketch/guitar/n03272010_6718-3.png 4 +sketch/guitar/n03272010_6718-4.png 4 +sketch/guitar/n03272010_6718-5.png 4 +sketch/guitar/n03272010_6725-1.png 4 +sketch/guitar/n03272010_6725-2.png 4 +sketch/guitar/n03272010_6725-3.png 4 +sketch/guitar/n03272010_6725-4.png 4 +sketch/guitar/n03272010_6725-5.png 4 +sketch/guitar/n03272010_6727-1.png 4 +sketch/guitar/n03272010_6727-2.png 4 +sketch/guitar/n03272010_6727-3.png 4 +sketch/guitar/n03272010_6727-4.png 4 +sketch/guitar/n03272010_6727-5.png 4 +sketch/guitar/n03272010_6737-1.png 4 +sketch/guitar/n03272010_6737-2.png 4 +sketch/guitar/n03272010_6737-3.png 4 +sketch/guitar/n03272010_6737-4.png 4 +sketch/guitar/n03272010_6737-5.png 4 +sketch/guitar/n03272010_6737-6.png 4 +sketch/guitar/n03272010_6799-1.png 4 +sketch/guitar/n03272010_6799-2.png 4 +sketch/guitar/n03272010_6799-3.png 4 +sketch/guitar/n03272010_6799-4.png 4 +sketch/guitar/n03272010_6799-5.png 4 +sketch/guitar/n03272010_6809-1.png 4 +sketch/guitar/n03272010_6809-2.png 4 +sketch/guitar/n03272010_6809-3.png 4 +sketch/guitar/n03272010_6809-4.png 4 +sketch/guitar/n03272010_6809-5.png 4 +sketch/guitar/n03272010_6820-1.png 4 +sketch/guitar/n03272010_6820-2.png 4 +sketch/guitar/n03272010_6820-3.png 4 +sketch/guitar/n03272010_6820-4.png 4 +sketch/guitar/n03272010_6820-5.png 4 +sketch/guitar/n03272010_6926-1.png 4 +sketch/guitar/n03272010_6926-2.png 4 +sketch/guitar/n03272010_6926-3.png 4 +sketch/guitar/n03272010_6926-4.png 4 +sketch/guitar/n03272010_6926-5.png 4 +sketch/guitar/n03272010_7000-1.png 4 +sketch/guitar/n03272010_7000-2.png 4 +sketch/guitar/n03272010_7000-3.png 4 +sketch/guitar/n03272010_7000-4.png 4 +sketch/guitar/n03272010_7000-5.png 4 +sketch/guitar/n03272010_7092-1.png 4 +sketch/guitar/n03272010_7092-2.png 4 +sketch/guitar/n03272010_7092-3.png 4 +sketch/guitar/n03272010_7092-4.png 4 +sketch/guitar/n03272010_7092-5.png 4 +sketch/guitar/n03272010_7383-1.png 4 +sketch/guitar/n03272010_7383-2.png 4 +sketch/guitar/n03272010_7383-3.png 4 +sketch/guitar/n03272010_7383-4.png 4 +sketch/guitar/n03272010_7383-5.png 4 +sketch/guitar/n03272010_7390-1.png 4 +sketch/guitar/n03272010_7390-2.png 4 +sketch/guitar/n03272010_7390-3.png 4 +sketch/guitar/n03272010_7390-4.png 4 +sketch/guitar/n03272010_7390-5.png 4 +sketch/guitar/n03272010_7635-1.png 4 +sketch/guitar/n03272010_7635-2.png 4 +sketch/guitar/n03272010_7635-3.png 4 +sketch/guitar/n03272010_7635-4.png 4 +sketch/guitar/n03272010_7635-5.png 4 +sketch/guitar/n03272010_7729-1.png 4 +sketch/guitar/n03272010_7729-2.png 4 +sketch/guitar/n03272010_7729-3.png 4 +sketch/guitar/n03272010_7729-4.png 4 +sketch/guitar/n03272010_7729-5.png 4 +sketch/guitar/n03272010_9557-1.png 4 +sketch/guitar/n03272010_9557-2.png 4 +sketch/guitar/n03272010_9557-3.png 4 +sketch/guitar/n03272010_9557-4.png 4 +sketch/guitar/n03272010_9557-5.png 4 +sketch/guitar/n03272010_9557-6.png 4 +sketch/guitar/n03272010_9858-1.png 4 +sketch/guitar/n03272010_9858-2.png 4 +sketch/guitar/n03272010_9858-3.png 4 +sketch/guitar/n03272010_9858-4.png 4 +sketch/guitar/n03272010_9858-5.png 4 +sketch/guitar/n03272010_9899-1.png 4 +sketch/guitar/n03272010_9899-2.png 4 +sketch/guitar/n03272010_9899-3.png 4 +sketch/guitar/n03272010_9899-4.png 4 +sketch/guitar/n03272010_9899-5.png 4 +sketch/guitar/n03272010_10441-1.png 4 +sketch/guitar/n03272010_10441-2.png 4 +sketch/guitar/n03272010_10441-3.png 4 +sketch/guitar/n03272010_10441-4.png 4 +sketch/guitar/n03272010_10441-5.png 4 +sketch/guitar/n03272010_10795-1.png 4 +sketch/guitar/n03272010_10795-2.png 4 +sketch/guitar/n03272010_10795-3.png 4 +sketch/guitar/n03272010_10795-4.png 4 +sketch/guitar/n03272010_10795-5.png 4 +sketch/guitar/n03272010_11646-1.png 4 +sketch/guitar/n03272010_11646-2.png 4 +sketch/guitar/n03272010_11646-3.png 4 +sketch/guitar/n03272010_11646-4.png 4 +sketch/guitar/n03272010_11646-5.png 4 +sketch/guitar/n03272010_12151-1.png 4 +sketch/guitar/n03272010_12151-2.png 4 +sketch/guitar/n03272010_12151-3.png 4 +sketch/guitar/n03272010_12151-4.png 4 +sketch/guitar/n03272010_12151-5.png 4 +sketch/guitar/n03272010_12468-1.png 4 +sketch/guitar/n03272010_12468-2.png 4 +sketch/guitar/n03272010_12468-3.png 4 +sketch/guitar/n03272010_12468-4.png 4 +sketch/guitar/n03272010_12468-5.png 4 +sketch/guitar/n03467517_3203-1.png 4 +sketch/guitar/n03467517_3203-2.png 4 +sketch/guitar/n03467517_3203-3.png 4 +sketch/guitar/n03467517_3203-4.png 4 +sketch/guitar/n03467517_3203-5.png 4 +sketch/guitar/n03467517_6423-1.png 4 +sketch/guitar/n03467517_6423-2.png 4 +sketch/guitar/n03467517_6423-3.png 4 +sketch/guitar/n03467517_6423-4.png 4 +sketch/guitar/n03467517_6423-5.png 4 +sketch/guitar/n03467517_7007-1.png 4 +sketch/guitar/n03467517_7007-2.png 4 +sketch/guitar/n03467517_7007-3.png 4 +sketch/guitar/n03467517_7007-4.png 4 +sketch/guitar/n03467517_7007-5.png 4 +sketch/guitar/n03467517_7007-6.png 4 +sketch/guitar/n03467517_8929-1.png 4 +sketch/guitar/n03467517_8929-2.png 4 +sketch/guitar/n03467517_8929-3.png 4 +sketch/guitar/n03467517_8929-4.png 4 +sketch/guitar/n03467517_8929-5.png 4 +sketch/guitar/n03467517_11020-1.png 4 +sketch/guitar/n03467517_11020-2.png 4 +sketch/guitar/n03467517_11020-3.png 4 +sketch/guitar/n03467517_11020-4.png 4 +sketch/guitar/n03467517_11020-5.png 4 +sketch/guitar/n03467517_12925-1.png 4 +sketch/guitar/n03467517_12925-2.png 4 +sketch/guitar/n03467517_12925-3.png 4 +sketch/guitar/n03467517_12925-4.png 4 +sketch/guitar/n03467517_12925-5.png 4 +sketch/guitar/n03467517_16911-1.png 4 +sketch/guitar/n03467517_16911-2.png 4 +sketch/guitar/n03467517_16911-3.png 4 +sketch/guitar/n03467517_16911-4.png 4 +sketch/guitar/n03467517_16911-5.png 4 +sketch/guitar/n03467517_17233-1.png 4 +sketch/guitar/n03467517_17233-2.png 4 +sketch/guitar/n03467517_17233-3.png 4 +sketch/guitar/n03467517_17233-4.png 4 +sketch/guitar/n03467517_17233-5.png 4 +sketch/guitar/n03467517_19701-1.png 4 +sketch/guitar/n03467517_19701-2.png 4 +sketch/guitar/n03467517_19701-3.png 4 +sketch/guitar/n03467517_19701-4.png 4 +sketch/guitar/n03467517_19701-5.png 4 +sketch/guitar/n03467517_21782-1.png 4 +sketch/guitar/n03467517_21782-2.png 4 +sketch/guitar/n03467517_21782-3.png 4 +sketch/guitar/n03467517_21782-4.png 4 +sketch/guitar/n03467517_21782-5.png 4 +sketch/guitar/n03467517_21884-1.png 4 +sketch/guitar/n03467517_21884-2.png 4 +sketch/guitar/n03467517_21884-3.png 4 +sketch/guitar/n03467517_21884-4.png 4 +sketch/guitar/n03467517_21884-5.png 4 +sketch/guitar/n03467517_21884-6.png 4 +sketch/guitar/n03467517_22246-1.png 4 +sketch/guitar/n03467517_22246-2.png 4 +sketch/guitar/n03467517_22246-3.png 4 +sketch/guitar/n03467517_22246-4.png 4 +sketch/guitar/n03467517_22246-5.png 4 +sketch/guitar/n03467517_22246-6.png 4 +sketch/guitar/n03467517_22374-1.png 4 +sketch/guitar/n03467517_22374-2.png 4 +sketch/guitar/n03467517_22374-3.png 4 +sketch/guitar/n03467517_22374-4.png 4 +sketch/guitar/n03467517_22374-5.png 4 +sketch/guitar/n03467517_22785-1.png 4 +sketch/guitar/n03467517_22785-2.png 4 +sketch/guitar/n03467517_22785-3.png 4 +sketch/guitar/n03467517_22785-4.png 4 +sketch/guitar/n03467517_22785-5.png 4 +sketch/guitar/n03467517_22871-1.png 4 +sketch/guitar/n03467517_22871-2.png 4 +sketch/guitar/n03467517_22871-3.png 4 +sketch/guitar/n03467517_22871-4.png 4 +sketch/guitar/n03467517_22871-5.png 4 +sketch/guitar/n03467517_23229-1.png 4 +sketch/guitar/n03467517_23229-2.png 4 +sketch/guitar/n03467517_23229-3.png 4 +sketch/guitar/n03467517_23229-4.png 4 +sketch/guitar/n03467517_23229-5.png 4 +sketch/guitar/n03467517_24525-1.png 4 +sketch/guitar/n03467517_24525-2.png 4 +sketch/guitar/n03467517_24525-3.png 4 +sketch/guitar/n03467517_24525-4.png 4 +sketch/guitar/n03467517_24525-5.png 4 +sketch/guitar/n03467517_24525-6.png 4 +sketch/horse/n02374451_54-1.png 5 +sketch/horse/n02374451_54-2.png 5 +sketch/horse/n02374451_54-3.png 5 +sketch/horse/n02374451_54-4.png 5 +sketch/horse/n02374451_54-5.png 5 +sketch/horse/n02374451_54-6.png 5 +sketch/horse/n02374451_54-7.png 5 +sketch/horse/n02374451_54-8.png 5 +sketch/horse/n02374451_54-9.png 5 +sketch/horse/n02374451_54-10.png 5 +sketch/horse/n02374451_245-1.png 5 +sketch/horse/n02374451_245-2.png 5 +sketch/horse/n02374451_245-3.png 5 +sketch/horse/n02374451_245-4.png 5 +sketch/horse/n02374451_245-5.png 5 +sketch/horse/n02374451_245-6.png 5 +sketch/horse/n02374451_257-1.png 5 +sketch/horse/n02374451_257-2.png 5 +sketch/horse/n02374451_257-3.png 5 +sketch/horse/n02374451_257-4.png 5 +sketch/horse/n02374451_257-5.png 5 +sketch/horse/n02374451_257-6.png 5 +sketch/horse/n02374451_257-7.png 5 +sketch/horse/n02374451_262-1.png 5 +sketch/horse/n02374451_262-2.png 5 +sketch/horse/n02374451_262-3.png 5 +sketch/horse/n02374451_262-4.png 5 +sketch/horse/n02374451_262-5.png 5 +sketch/horse/n02374451_262-6.png 5 +sketch/horse/n02374451_262-7.png 5 +sketch/horse/n02374451_262-8.png 5 +sketch/horse/n02374451_262-9.png 5 +sketch/horse/n02374451_262-10.png 5 +sketch/horse/n02374451_262-11.png 5 +sketch/horse/n02374451_262-12.png 5 +sketch/horse/n02374451_276-1.png 5 +sketch/horse/n02374451_276-2.png 5 +sketch/horse/n02374451_276-3.png 5 +sketch/horse/n02374451_276-4.png 5 +sketch/horse/n02374451_276-5.png 5 +sketch/horse/n02374451_276-6.png 5 +sketch/horse/n02374451_276-7.png 5 +sketch/horse/n02374451_276-8.png 5 +sketch/horse/n02374451_276-9.png 5 +sketch/horse/n02374451_276-10.png 5 +sketch/horse/n02374451_388-2.png 5 +sketch/horse/n02374451_388-3.png 5 +sketch/horse/n02374451_388-4.png 5 +sketch/horse/n02374451_388-5.png 5 +sketch/horse/n02374451_388-6.png 5 +sketch/horse/n02374451_388-7.png 5 +sketch/horse/n02374451_388-8.png 5 +sketch/horse/n02374451_388-9.png 5 +sketch/horse/n02374451_388-10.png 5 +sketch/horse/n02374451_468-1.png 5 +sketch/horse/n02374451_468-2.png 5 +sketch/horse/n02374451_468-3.png 5 +sketch/horse/n02374451_468-4.png 5 +sketch/horse/n02374451_468-5.png 5 +sketch/horse/n02374451_468-6.png 5 +sketch/horse/n02374451_468-7.png 5 +sketch/horse/n02374451_468-8.png 5 +sketch/horse/n02374451_468-9.png 5 +sketch/horse/n02374451_468-10.png 5 +sketch/horse/n02374451_490-1.png 5 +sketch/horse/n02374451_490-2.png 5 +sketch/horse/n02374451_490-3.png 5 +sketch/horse/n02374451_490-4.png 5 +sketch/horse/n02374451_490-5.png 5 +sketch/horse/n02374451_490-6.png 5 +sketch/horse/n02374451_490-7.png 5 +sketch/horse/n02374451_503-1.png 5 +sketch/horse/n02374451_503-2.png 5 +sketch/horse/n02374451_503-3.png 5 +sketch/horse/n02374451_503-4.png 5 +sketch/horse/n02374451_503-5.png 5 +sketch/horse/n02374451_503-6.png 5 +sketch/horse/n02374451_557-1.png 5 +sketch/horse/n02374451_557-2.png 5 +sketch/horse/n02374451_557-3.png 5 +sketch/horse/n02374451_557-4.png 5 +sketch/horse/n02374451_557-5.png 5 +sketch/horse/n02374451_597-1.png 5 +sketch/horse/n02374451_597-2.png 5 +sketch/horse/n02374451_597-3.png 5 +sketch/horse/n02374451_597-4.png 5 +sketch/horse/n02374451_597-5.png 5 +sketch/horse/n02374451_597-6.png 5 +sketch/horse/n02374451_597-7.png 5 +sketch/horse/n02374451_777-1.png 5 +sketch/horse/n02374451_777-2.png 5 +sketch/horse/n02374451_777-3.png 5 +sketch/horse/n02374451_777-4.png 5 +sketch/horse/n02374451_777-5.png 5 +sketch/horse/n02374451_777-6.png 5 +sketch/horse/n02374451_779-1.png 5 +sketch/horse/n02374451_779-2.png 5 +sketch/horse/n02374451_779-3.png 5 +sketch/horse/n02374451_779-4.png 5 +sketch/horse/n02374451_779-5.png 5 +sketch/horse/n02374451_779-6.png 5 +sketch/horse/n02374451_779-7.png 5 +sketch/horse/n02374451_779-8.png 5 +sketch/horse/n02374451_779-9.png 5 +sketch/horse/n02374451_916-1.png 5 +sketch/horse/n02374451_916-2.png 5 +sketch/horse/n02374451_916-3.png 5 +sketch/horse/n02374451_916-4.png 5 +sketch/horse/n02374451_916-5.png 5 +sketch/horse/n02374451_916-6.png 5 +sketch/horse/n02374451_925-1.png 5 +sketch/horse/n02374451_925-2.png 5 +sketch/horse/n02374451_925-3.png 5 +sketch/horse/n02374451_925-4.png 5 +sketch/horse/n02374451_925-5.png 5 +sketch/horse/n02374451_925-6.png 5 +sketch/horse/n02374451_925-7.png 5 +sketch/horse/n02374451_929-1.png 5 +sketch/horse/n02374451_929-2.png 5 +sketch/horse/n02374451_929-3.png 5 +sketch/horse/n02374451_929-4.png 5 +sketch/horse/n02374451_929-5.png 5 +sketch/horse/n02374451_929-6.png 5 +sketch/horse/n02374451_1189-1.png 5 +sketch/horse/n02374451_1189-2.png 5 +sketch/horse/n02374451_1189-3.png 5 +sketch/horse/n02374451_1189-4.png 5 +sketch/horse/n02374451_1189-5.png 5 +sketch/horse/n02374451_1189-6.png 5 +sketch/horse/n02374451_1189-7.png 5 +sketch/horse/n02374451_1234-1.png 5 +sketch/horse/n02374451_1234-2.png 5 +sketch/horse/n02374451_1234-3.png 5 +sketch/horse/n02374451_1234-4.png 5 +sketch/horse/n02374451_1234-5.png 5 +sketch/horse/n02374451_1234-6.png 5 +sketch/horse/n02374451_1340-1.png 5 +sketch/horse/n02374451_1340-2.png 5 +sketch/horse/n02374451_1340-3.png 5 +sketch/horse/n02374451_1340-4.png 5 +sketch/horse/n02374451_1340-5.png 5 +sketch/horse/n02374451_1340-6.png 5 +sketch/horse/n02374451_1340-7.png 5 +sketch/horse/n02374451_1340-8.png 5 +sketch/horse/n02374451_1340-9.png 5 +sketch/horse/n02374451_1340-10.png 5 +sketch/horse/n02374451_1340-11.png 5 +sketch/horse/n02374451_1443-1.png 5 +sketch/horse/n02374451_1443-2.png 5 +sketch/horse/n02374451_1443-3.png 5 +sketch/horse/n02374451_1443-4.png 5 +sketch/horse/n02374451_1443-5.png 5 +sketch/horse/n02374451_1443-6.png 5 +sketch/horse/n02374451_1443-7.png 5 +sketch/horse/n02374451_1443-8.png 5 +sketch/horse/n02374451_1695-1.png 5 +sketch/horse/n02374451_1695-2.png 5 +sketch/horse/n02374451_1695-3.png 5 +sketch/horse/n02374451_1695-4.png 5 +sketch/horse/n02374451_1695-5.png 5 +sketch/horse/n02374451_1695-6.png 5 +sketch/horse/n02374451_1695-7.png 5 +sketch/horse/n02374451_2233-1.png 5 +sketch/horse/n02374451_2233-2.png 5 +sketch/horse/n02374451_2233-3.png 5 +sketch/horse/n02374451_2233-4.png 5 +sketch/horse/n02374451_2233-5.png 5 +sketch/horse/n02374451_2233-6.png 5 +sketch/horse/n02374451_2233-7.png 5 +sketch/horse/n02374451_2248-1.png 5 +sketch/horse/n02374451_2248-2.png 5 +sketch/horse/n02374451_2248-3.png 5 +sketch/horse/n02374451_2248-4.png 5 +sketch/horse/n02374451_2248-5.png 5 +sketch/horse/n02374451_2248-6.png 5 +sketch/horse/n02374451_2248-7.png 5 +sketch/horse/n02374451_2248-8.png 5 +sketch/horse/n02374451_2372-1.png 5 +sketch/horse/n02374451_2372-2.png 5 +sketch/horse/n02374451_2372-3.png 5 +sketch/horse/n02374451_2372-4.png 5 +sketch/horse/n02374451_2372-5.png 5 +sketch/horse/n02374451_2372-6.png 5 +sketch/horse/n02374451_2372-7.png 5 +sketch/horse/n02374451_2372-8.png 5 +sketch/horse/n02374451_2478-1.png 5 +sketch/horse/n02374451_2478-2.png 5 +sketch/horse/n02374451_2478-3.png 5 +sketch/horse/n02374451_2478-4.png 5 +sketch/horse/n02374451_2478-5.png 5 +sketch/horse/n02374451_2616-1.png 5 +sketch/horse/n02374451_2616-2.png 5 +sketch/horse/n02374451_2616-3.png 5 +sketch/horse/n02374451_2616-4.png 5 +sketch/horse/n02374451_2616-5.png 5 +sketch/horse/n02374451_2616-6.png 5 +sketch/horse/n02374451_2616-7.png 5 +sketch/horse/n02374451_2616-8.png 5 +sketch/horse/n02374451_2616-9.png 5 +sketch/horse/n02374451_2616-10.png 5 +sketch/horse/n02374451_2733-1.png 5 +sketch/horse/n02374451_2733-2.png 5 +sketch/horse/n02374451_2733-3.png 5 +sketch/horse/n02374451_2733-4.png 5 +sketch/horse/n02374451_2733-5.png 5 +sketch/horse/n02374451_2733-6.png 5 +sketch/horse/n02374451_2733-7.png 5 +sketch/horse/n02374451_2743-1.png 5 +sketch/horse/n02374451_2743-2.png 5 +sketch/horse/n02374451_2743-3.png 5 +sketch/horse/n02374451_2743-4.png 5 +sketch/horse/n02374451_2743-5.png 5 +sketch/horse/n02374451_2743-6.png 5 +sketch/horse/n02374451_2743-7.png 5 +sketch/horse/n02374451_2825-1.png 5 +sketch/horse/n02374451_2825-2.png 5 +sketch/horse/n02374451_2825-3.png 5 +sketch/horse/n02374451_2825-4.png 5 +sketch/horse/n02374451_2825-5.png 5 +sketch/horse/n02374451_2825-6.png 5 +sketch/horse/n02374451_2825-7.png 5 +sketch/horse/n02374451_2825-8.png 5 +sketch/horse/n02374451_2825-9.png 5 +sketch/horse/n02374451_2825-10.png 5 +sketch/horse/n02374451_2846-1.png 5 +sketch/horse/n02374451_2846-2.png 5 +sketch/horse/n02374451_2846-3.png 5 +sketch/horse/n02374451_2846-4.png 5 +sketch/horse/n02374451_2846-5.png 5 +sketch/horse/n02374451_2846-6.png 5 +sketch/horse/n02374451_2846-7.png 5 +sketch/horse/n02374451_2846-8.png 5 +sketch/horse/n02374451_2846-9.png 5 +sketch/horse/n02374451_3388-1.png 5 +sketch/horse/n02374451_3388-2.png 5 +sketch/horse/n02374451_3388-3.png 5 +sketch/horse/n02374451_3388-4.png 5 +sketch/horse/n02374451_3388-5.png 5 +sketch/horse/n02374451_3388-6.png 5 +sketch/horse/n02374451_3388-7.png 5 +sketch/horse/n02374451_3388-8.png 5 +sketch/horse/n02374451_3388-9.png 5 +sketch/horse/n02374451_3808-1.png 5 +sketch/horse/n02374451_3808-2.png 5 +sketch/horse/n02374451_3808-3.png 5 +sketch/horse/n02374451_3808-4.png 5 +sketch/horse/n02374451_3808-5.png 5 +sketch/horse/n02374451_3808-6.png 5 +sketch/horse/n02374451_3808-7.png 5 +sketch/horse/n02374451_3808-8.png 5 +sketch/horse/n02374451_3808-9.png 5 +sketch/horse/n02374451_4538-1.png 5 +sketch/horse/n02374451_4538-2.png 5 +sketch/horse/n02374451_4538-3.png 5 +sketch/horse/n02374451_4538-4.png 5 +sketch/horse/n02374451_4538-5.png 5 +sketch/horse/n02374451_4538-6.png 5 +sketch/horse/n02374451_4538-7.png 5 +sketch/horse/n02374451_4538-8.png 5 +sketch/horse/n02374451_4538-9.png 5 +sketch/horse/n02374451_4553-1.png 5 +sketch/horse/n02374451_4553-2.png 5 +sketch/horse/n02374451_4553-3.png 5 +sketch/horse/n02374451_4553-4.png 5 +sketch/horse/n02374451_4553-5.png 5 +sketch/horse/n02374451_4553-6.png 5 +sketch/horse/n02374451_4553-7.png 5 +sketch/horse/n02374451_4795-1.png 5 +sketch/horse/n02374451_4795-2.png 5 +sketch/horse/n02374451_4795-3.png 5 +sketch/horse/n02374451_4795-4.png 5 +sketch/horse/n02374451_4795-5.png 5 +sketch/horse/n02374451_4795-6.png 5 +sketch/horse/n02374451_4795-7.png 5 +sketch/horse/n02374451_4795-8.png 5 +sketch/horse/n02374451_4818-1.png 5 +sketch/horse/n02374451_4818-2.png 5 +sketch/horse/n02374451_4818-3.png 5 +sketch/horse/n02374451_4818-4.png 5 +sketch/horse/n02374451_4818-5.png 5 +sketch/horse/n02374451_4818-6.png 5 +sketch/horse/n02374451_4818-7.png 5 +sketch/horse/n02374451_4963-1.png 5 +sketch/horse/n02374451_4963-2.png 5 +sketch/horse/n02374451_4963-3.png 5 +sketch/horse/n02374451_4963-4.png 5 +sketch/horse/n02374451_4963-5.png 5 +sketch/horse/n02374451_4963-6.png 5 +sketch/horse/n02374451_5084-1.png 5 +sketch/horse/n02374451_5084-2.png 5 +sketch/horse/n02374451_5084-3.png 5 +sketch/horse/n02374451_5084-4.png 5 +sketch/horse/n02374451_5084-5.png 5 +sketch/horse/n02374451_5084-6.png 5 +sketch/horse/n02374451_6192-1.png 5 +sketch/horse/n02374451_6192-2.png 5 +sketch/horse/n02374451_6192-3.png 5 +sketch/horse/n02374451_6192-4.png 5 +sketch/horse/n02374451_6192-5.png 5 +sketch/horse/n02374451_6192-6.png 5 +sketch/horse/n02374451_6192-7.png 5 +sketch/horse/n02374451_6207-1.png 5 +sketch/horse/n02374451_6207-2.png 5 +sketch/horse/n02374451_6207-3.png 5 +sketch/horse/n02374451_6207-4.png 5 +sketch/horse/n02374451_6207-5.png 5 +sketch/horse/n02374451_6207-6.png 5 +sketch/horse/n02374451_7631-1.png 5 +sketch/horse/n02374451_7631-2.png 5 +sketch/horse/n02374451_7631-3.png 5 +sketch/horse/n02374451_7631-4.png 5 +sketch/horse/n02374451_7631-5.png 5 +sketch/horse/n02374451_7631-6.png 5 +sketch/horse/n02374451_7631-7.png 5 +sketch/horse/n02374451_8065-1.png 5 +sketch/horse/n02374451_8065-2.png 5 +sketch/horse/n02374451_8065-3.png 5 +sketch/horse/n02374451_8065-4.png 5 +sketch/horse/n02374451_8065-5.png 5 +sketch/horse/n02374451_8065-6.png 5 +sketch/horse/n02374451_8269-1.png 5 +sketch/horse/n02374451_8269-2.png 5 +sketch/horse/n02374451_8269-3.png 5 +sketch/horse/n02374451_8269-4.png 5 +sketch/horse/n02374451_8269-5.png 5 +sketch/horse/n02374451_8269-6.png 5 +sketch/horse/n02374451_8269-7.png 5 +sketch/horse/n02374451_8269-8.png 5 +sketch/horse/n02374451_8269-9.png 5 +sketch/horse/n02374451_8526-1.png 5 +sketch/horse/n02374451_8526-2.png 5 +sketch/horse/n02374451_8526-3.png 5 +sketch/horse/n02374451_8526-4.png 5 +sketch/horse/n02374451_8526-5.png 5 +sketch/horse/n02374451_8526-6.png 5 +sketch/horse/n02374451_8718-1.png 5 +sketch/horse/n02374451_8718-2.png 5 +sketch/horse/n02374451_8718-3.png 5 +sketch/horse/n02374451_8718-4.png 5 +sketch/horse/n02374451_8718-5.png 5 +sketch/horse/n02374451_8718-6.png 5 +sketch/horse/n02374451_8744-1.png 5 +sketch/horse/n02374451_8744-2.png 5 +sketch/horse/n02374451_8744-3.png 5 +sketch/horse/n02374451_8744-4.png 5 +sketch/horse/n02374451_8744-5.png 5 +sketch/horse/n02374451_8744-6.png 5 +sketch/horse/n02374451_8744-7.png 5 +sketch/horse/n02374451_8744-8.png 5 +sketch/horse/n02374451_8744-9.png 5 +sketch/horse/n02374451_8744-10.png 5 +sketch/horse/n02374451_8806-1.png 5 +sketch/horse/n02374451_8806-2.png 5 +sketch/horse/n02374451_8806-3.png 5 +sketch/horse/n02374451_8806-4.png 5 +sketch/horse/n02374451_8806-5.png 5 +sketch/horse/n02374451_8806-6.png 5 +sketch/horse/n02374451_8806-7.png 5 +sketch/horse/n02374451_8806-8.png 5 +sketch/horse/n02374451_9064-1.png 5 +sketch/horse/n02374451_9064-2.png 5 +sketch/horse/n02374451_9064-3.png 5 +sketch/horse/n02374451_9064-4.png 5 +sketch/horse/n02374451_9064-5.png 5 +sketch/horse/n02374451_9064-6.png 5 +sketch/horse/n02374451_9225-1.png 5 +sketch/horse/n02374451_9225-2.png 5 +sketch/horse/n02374451_9225-3.png 5 +sketch/horse/n02374451_9225-4.png 5 +sketch/horse/n02374451_9225-5.png 5 +sketch/horse/n02374451_9225-6.png 5 +sketch/horse/n02374451_9225-7.png 5 +sketch/horse/n02374451_9225-8.png 5 +sketch/horse/n02374451_9443-1.png 5 +sketch/horse/n02374451_9443-2.png 5 +sketch/horse/n02374451_9443-3.png 5 +sketch/horse/n02374451_9443-4.png 5 +sketch/horse/n02374451_9443-5.png 5 +sketch/horse/n02374451_9443-6.png 5 +sketch/horse/n02374451_9443-7.png 5 +sketch/horse/n02374451_9892-1.png 5 +sketch/horse/n02374451_9892-2.png 5 +sketch/horse/n02374451_9892-3.png 5 +sketch/horse/n02374451_9892-4.png 5 +sketch/horse/n02374451_9892-5.png 5 +sketch/horse/n02374451_9892-6.png 5 +sketch/horse/n02374451_9892-7.png 5 +sketch/horse/n02374451_10081-1.png 5 +sketch/horse/n02374451_10081-2.png 5 +sketch/horse/n02374451_10081-3.png 5 +sketch/horse/n02374451_10081-4.png 5 +sketch/horse/n02374451_10081-5.png 5 +sketch/horse/n02374451_10081-6.png 5 +sketch/horse/n02374451_10098-1.png 5 +sketch/horse/n02374451_10098-2.png 5 +sketch/horse/n02374451_10098-3.png 5 +sketch/horse/n02374451_10098-4.png 5 +sketch/horse/n02374451_10098-5.png 5 +sketch/horse/n02374451_10098-6.png 5 +sketch/horse/n02374451_10098-7.png 5 +sketch/horse/n02374451_10099-1.png 5 +sketch/horse/n02374451_10099-2.png 5 +sketch/horse/n02374451_10099-3.png 5 +sketch/horse/n02374451_10099-4.png 5 +sketch/horse/n02374451_10099-5.png 5 +sketch/horse/n02374451_10099-6.png 5 +sketch/horse/n02374451_10099-7.png 5 +sketch/horse/n02374451_10099-8.png 5 +sketch/horse/n02374451_10099-9.png 5 +sketch/horse/n02374451_10118-1.png 5 +sketch/horse/n02374451_10118-2.png 5 +sketch/horse/n02374451_10118-3.png 5 +sketch/horse/n02374451_10118-4.png 5 +sketch/horse/n02374451_10118-5.png 5 +sketch/horse/n02374451_10331-1.png 5 +sketch/horse/n02374451_10331-2.png 5 +sketch/horse/n02374451_10331-3.png 5 +sketch/horse/n02374451_10331-4.png 5 +sketch/horse/n02374451_10331-5.png 5 +sketch/horse/n02374451_10669-1.png 5 +sketch/horse/n02374451_10669-2.png 5 +sketch/horse/n02374451_10669-3.png 5 +sketch/horse/n02374451_10669-4.png 5 +sketch/horse/n02374451_10669-5.png 5 +sketch/horse/n02374451_10669-6.png 5 +sketch/horse/n02374451_10669-7.png 5 +sketch/horse/n02374451_10669-8.png 5 +sketch/horse/n02374451_10669-9.png 5 +sketch/horse/n02374451_10761-1.png 5 +sketch/horse/n02374451_10761-2.png 5 +sketch/horse/n02374451_10761-3.png 5 +sketch/horse/n02374451_10761-4.png 5 +sketch/horse/n02374451_10761-5.png 5 +sketch/horse/n02374451_10761-6.png 5 +sketch/horse/n02374451_10761-7.png 5 +sketch/horse/n02374451_10761-8.png 5 +sketch/horse/n02374451_10761-9.png 5 +sketch/horse/n02374451_10761-10.png 5 +sketch/horse/n02374451_10809-1.png 5 +sketch/horse/n02374451_10809-2.png 5 +sketch/horse/n02374451_10809-4.png 5 +sketch/horse/n02374451_10809-5.png 5 +sketch/horse/n02374451_10809-6.png 5 +sketch/horse/n02374451_10809-7.png 5 +sketch/horse/n02374451_10809-8.png 5 +sketch/horse/n02374451_11479-1.png 5 +sketch/horse/n02374451_11479-2.png 5 +sketch/horse/n02374451_11479-3.png 5 +sketch/horse/n02374451_11479-4.png 5 +sketch/horse/n02374451_11479-5.png 5 +sketch/horse/n02374451_11479-6.png 5 +sketch/horse/n02374451_11479-7.png 5 +sketch/horse/n02374451_11483-1.png 5 +sketch/horse/n02374451_11483-2.png 5 +sketch/horse/n02374451_11483-3.png 5 +sketch/horse/n02374451_11483-4.png 5 +sketch/horse/n02374451_11483-5.png 5 +sketch/horse/n02374451_11483-6.png 5 +sketch/horse/n02374451_11492-1.png 5 +sketch/horse/n02374451_11492-2.png 5 +sketch/horse/n02374451_11492-3.png 5 +sketch/horse/n02374451_11492-4.png 5 +sketch/horse/n02374451_11492-5.png 5 +sketch/horse/n02374451_11492-6.png 5 +sketch/horse/n02374451_11894-1.png 5 +sketch/horse/n02374451_11894-2.png 5 +sketch/horse/n02374451_11894-3.png 5 +sketch/horse/n02374451_11894-4.png 5 +sketch/horse/n02374451_11894-5.png 5 +sketch/horse/n02374451_11894-6.png 5 +sketch/horse/n02374451_11894-7.png 5 +sketch/horse/n02374451_11894-8.png 5 +sketch/horse/n02374451_11894-9.png 5 +sketch/horse/n02374451_12128-1.png 5 +sketch/horse/n02374451_12128-2.png 5 +sketch/horse/n02374451_12128-3.png 5 +sketch/horse/n02374451_12128-4.png 5 +sketch/horse/n02374451_12128-5.png 5 +sketch/horse/n02374451_12128-6.png 5 +sketch/horse/n02374451_12128-7.png 5 +sketch/horse/n02374451_12128-8.png 5 +sketch/horse/n02374451_12174-1.png 5 +sketch/horse/n02374451_12174-2.png 5 +sketch/horse/n02374451_12174-3.png 5 +sketch/horse/n02374451_12174-4.png 5 +sketch/horse/n02374451_12174-5.png 5 +sketch/horse/n02374451_12174-6.png 5 +sketch/horse/n02374451_12200-1.png 5 +sketch/horse/n02374451_12200-2.png 5 +sketch/horse/n02374451_12200-3.png 5 +sketch/horse/n02374451_12200-4.png 5 +sketch/horse/n02374451_12200-5.png 5 +sketch/horse/n02374451_12200-6.png 5 +sketch/horse/n02374451_12200-7.png 5 +sketch/horse/n02374451_12225-1.png 5 +sketch/horse/n02374451_12225-2.png 5 +sketch/horse/n02374451_12225-3.png 5 +sketch/horse/n02374451_12225-4.png 5 +sketch/horse/n02374451_12225-5.png 5 +sketch/horse/n02374451_12225-6.png 5 +sketch/horse/n02374451_12230-1.png 5 +sketch/horse/n02374451_12230-2.png 5 +sketch/horse/n02374451_12230-3.png 5 +sketch/horse/n02374451_12230-4.png 5 +sketch/horse/n02374451_12230-5.png 5 +sketch/horse/n02374451_12230-6.png 5 +sketch/horse/n02374451_12230-7.png 5 +sketch/horse/n02374451_12239-1.png 5 +sketch/horse/n02374451_12239-2.png 5 +sketch/horse/n02374451_12239-3.png 5 +sketch/horse/n02374451_12239-4.png 5 +sketch/horse/n02374451_12239-5.png 5 +sketch/horse/n02374451_12239-6.png 5 +sketch/horse/n02374451_12239-7.png 5 +sketch/horse/n02374451_12250-1.png 5 +sketch/horse/n02374451_12250-2.png 5 +sketch/horse/n02374451_12250-3.png 5 +sketch/horse/n02374451_12250-4.png 5 +sketch/horse/n02374451_12250-5.png 5 +sketch/horse/n02374451_12250-6.png 5 +sketch/horse/n02374451_12250-7.png 5 +sketch/horse/n02374451_12254-1.png 5 +sketch/horse/n02374451_12254-2.png 5 +sketch/horse/n02374451_12254-3.png 5 +sketch/horse/n02374451_12254-4.png 5 +sketch/horse/n02374451_12254-5.png 5 +sketch/horse/n02374451_12254-6.png 5 +sketch/horse/n02374451_12254-7.png 5 +sketch/horse/n02374451_12328-1.png 5 +sketch/horse/n02374451_12328-2.png 5 +sketch/horse/n02374451_12328-3.png 5 +sketch/horse/n02374451_12328-4.png 5 +sketch/horse/n02374451_12328-5.png 5 +sketch/horse/n02374451_12328-6.png 5 +sketch/horse/n02374451_12328-7.png 5 +sketch/horse/n02374451_12328-8.png 5 +sketch/horse/n02374451_12328-9.png 5 +sketch/horse/n02374451_12328-10.png 5 +sketch/horse/n02374451_12418-1.png 5 +sketch/horse/n02374451_12418-2.png 5 +sketch/horse/n02374451_12418-3.png 5 +sketch/horse/n02374451_12418-4.png 5 +sketch/horse/n02374451_12418-5.png 5 +sketch/horse/n02374451_12418-6.png 5 +sketch/horse/n02374451_12418-7.png 5 +sketch/horse/n02374451_12418-8.png 5 +sketch/horse/n02374451_12418-9.png 5 +sketch/horse/n02374451_12418-10.png 5 +sketch/horse/n02374451_12792-1.png 5 +sketch/horse/n02374451_12792-2.png 5 +sketch/horse/n02374451_12792-3.png 5 +sketch/horse/n02374451_12792-4.png 5 +sketch/horse/n02374451_12792-5.png 5 +sketch/horse/n02374451_12792-6.png 5 +sketch/horse/n02374451_12792-7.png 5 +sketch/horse/n02374451_12792-8.png 5 +sketch/horse/n02374451_12792-9.png 5 +sketch/horse/n02374451_12792-10.png 5 +sketch/horse/n02374451_12847-1.png 5 +sketch/horse/n02374451_12847-2.png 5 +sketch/horse/n02374451_12847-3.png 5 +sketch/horse/n02374451_12847-4.png 5 +sketch/horse/n02374451_12847-5.png 5 +sketch/horse/n02374451_12847-6.png 5 +sketch/horse/n02374451_12847-7.png 5 +sketch/horse/n02374451_12847-8.png 5 +sketch/horse/n02374451_13132-1.png 5 +sketch/horse/n02374451_13132-2.png 5 +sketch/horse/n02374451_13132-3.png 5 +sketch/horse/n02374451_13132-4.png 5 +sketch/horse/n02374451_13132-5.png 5 +sketch/horse/n02374451_13132-6.png 5 +sketch/horse/n02374451_13132-7.png 5 +sketch/horse/n02374451_13136-1.png 5 +sketch/horse/n02374451_13136-2.png 5 +sketch/horse/n02374451_13136-3.png 5 +sketch/horse/n02374451_13136-4.png 5 +sketch/horse/n02374451_13136-5.png 5 +sketch/horse/n02374451_13159-1.png 5 +sketch/horse/n02374451_13159-2.png 5 +sketch/horse/n02374451_13159-3.png 5 +sketch/horse/n02374451_13159-4.png 5 +sketch/horse/n02374451_13159-5.png 5 +sketch/horse/n02374451_13159-6.png 5 +sketch/horse/n02374451_13159-7.png 5 +sketch/horse/n02374451_13159-8.png 5 +sketch/horse/n02374451_13171-1.png 5 +sketch/horse/n02374451_13171-2.png 5 +sketch/horse/n02374451_13171-3.png 5 +sketch/horse/n02374451_13171-4.png 5 +sketch/horse/n02374451_13171-5.png 5 +sketch/horse/n02374451_13171-6.png 5 +sketch/horse/n02374451_13718-1.png 5 +sketch/horse/n02374451_13718-2.png 5 +sketch/horse/n02374451_13718-3.png 5 +sketch/horse/n02374451_13718-4.png 5 +sketch/horse/n02374451_13718-5.png 5 +sketch/horse/n02374451_13718-6.png 5 +sketch/horse/n02374451_14119-1.png 5 +sketch/horse/n02374451_14119-2.png 5 +sketch/horse/n02374451_14119-3.png 5 +sketch/horse/n02374451_14119-4.png 5 +sketch/horse/n02374451_14119-5.png 5 +sketch/horse/n02374451_14119-6.png 5 +sketch/horse/n02374451_14119-7.png 5 +sketch/horse/n02374451_14119-8.png 5 +sketch/horse/n02374451_14119-9.png 5 +sketch/horse/n02374451_14233-1.png 5 +sketch/horse/n02374451_14233-2.png 5 +sketch/horse/n02374451_14233-3.png 5 +sketch/horse/n02374451_14233-4.png 5 +sketch/horse/n02374451_14233-5.png 5 +sketch/horse/n02374451_14399-1.png 5 +sketch/horse/n02374451_14399-2.png 5 +sketch/horse/n02374451_14399-3.png 5 +sketch/horse/n02374451_14399-4.png 5 +sketch/horse/n02374451_14399-5.png 5 +sketch/horse/n02374451_14399-6.png 5 +sketch/horse/n02374451_14399-7.png 5 +sketch/horse/n02374451_14425-10.png 5 +sketch/horse/n02374451_14425-1.png 5 +sketch/horse/n02374451_14425-2.png 5 +sketch/horse/n02374451_14425-3.png 5 +sketch/horse/n02374451_14425-4.png 5 +sketch/horse/n02374451_14425-5.png 5 +sketch/horse/n02374451_14425-6.png 5 +sketch/horse/n02374451_14425-7.png 5 +sketch/horse/n02374451_14425-8.png 5 +sketch/horse/n02374451_14425-9.png 5 +sketch/horse/n02374451_14738-1.png 5 +sketch/horse/n02374451_14738-2.png 5 +sketch/horse/n02374451_14738-3.png 5 +sketch/horse/n02374451_14738-4.png 5 +sketch/horse/n02374451_14738-5.png 5 +sketch/horse/n02374451_14738-6.png 5 +sketch/horse/n02374451_14738-7.png 5 +sketch/horse/n02374451_14846-1.png 5 +sketch/horse/n02374451_14846-2.png 5 +sketch/horse/n02374451_14846-3.png 5 +sketch/horse/n02374451_14846-4.png 5 +sketch/horse/n02374451_14846-5.png 5 +sketch/horse/n02374451_14846-6.png 5 +sketch/horse/n02374451_14846-7.png 5 +sketch/horse/n02374451_15307-1.png 5 +sketch/horse/n02374451_15307-2.png 5 +sketch/horse/n02374451_15307-3.png 5 +sketch/horse/n02374451_15307-4.png 5 +sketch/horse/n02374451_15307-5.png 5 +sketch/horse/n02374451_15307-6.png 5 +sketch/horse/n02374451_15440-1.png 5 +sketch/horse/n02374451_15440-2.png 5 +sketch/horse/n02374451_15440-3.png 5 +sketch/horse/n02374451_15440-4.png 5 +sketch/horse/n02374451_15440-5.png 5 +sketch/horse/n02374451_15440-6.png 5 +sketch/horse/n02374451_15453-1.png 5 +sketch/horse/n02374451_15453-2.png 5 +sketch/horse/n02374451_15453-3.png 5 +sketch/horse/n02374451_15453-4.png 5 +sketch/horse/n02374451_15453-5.png 5 +sketch/horse/n02374451_15453-6.png 5 +sketch/horse/n02374451_15453-7.png 5 +sketch/horse/n02374451_15669-1.png 5 +sketch/horse/n02374451_15669-2.png 5 +sketch/horse/n02374451_15669-3.png 5 +sketch/horse/n02374451_15669-4.png 5 +sketch/horse/n02374451_15669-5.png 5 +sketch/horse/n02374451_15669-6.png 5 +sketch/horse/n02374451_16194-1.png 5 +sketch/horse/n02374451_16194-2.png 5 +sketch/horse/n02374451_16194-3.png 5 +sketch/horse/n02374451_16194-4.png 5 +sketch/horse/n02374451_16194-5.png 5 +sketch/horse/n02374451_16194-6.png 5 +sketch/horse/n02374451_16358-1.png 5 +sketch/horse/n02374451_16358-2.png 5 +sketch/horse/n02374451_16358-3.png 5 +sketch/horse/n02374451_16358-4.png 5 +sketch/horse/n02374451_16358-5.png 5 +sketch/horse/n02374451_16358-6.png 5 +sketch/horse/n02374451_16948-1.png 5 +sketch/horse/n02374451_16948-2.png 5 +sketch/horse/n02374451_16948-3.png 5 +sketch/horse/n02374451_16948-4.png 5 +sketch/horse/n02374451_16948-5.png 5 +sketch/horse/n02374451_16948-6.png 5 +sketch/horse/n02374451_16948-7.png 5 +sketch/horse/n02374451_16948-8.png 5 +sketch/horse/n02374451_16948-9.png 5 +sketch/horse/n02374451_17043-1.png 5 +sketch/horse/n02374451_17043-2.png 5 +sketch/horse/n02374451_17043-3.png 5 +sketch/horse/n02374451_17043-4.png 5 +sketch/horse/n02374451_17043-5.png 5 +sketch/horse/n02374451_17043-6.png 5 +sketch/horse/n02374451_17384-1.png 5 +sketch/horse/n02374451_17384-2.png 5 +sketch/horse/n02374451_17384-3.png 5 +sketch/horse/n02374451_17384-4.png 5 +sketch/horse/n02374451_17384-5.png 5 +sketch/horse/n02374451_17384-6.png 5 +sketch/horse/n02374451_17384-7.png 5 +sketch/horse/n02374451_17384-8.png 5 +sketch/horse/n02374451_17474-1.png 5 +sketch/horse/n02374451_17474-2.png 5 +sketch/horse/n02374451_17474-3.png 5 +sketch/horse/n02374451_17474-4.png 5 +sketch/horse/n02374451_17474-5.png 5 +sketch/horse/n02374451_17474-6.png 5 +sketch/horse/n02374451_17474-7.png 5 +sketch/horse/n02374451_17474-8.png 5 +sketch/horse/n02374451_17634-1.png 5 +sketch/horse/n02374451_17634-2.png 5 +sketch/horse/n02374451_17634-3.png 5 +sketch/horse/n02374451_17634-4.png 5 +sketch/horse/n02374451_17634-5.png 5 +sketch/horse/n02374451_17634-6.png 5 +sketch/horse/n02374451_18192-1.png 5 +sketch/horse/n02374451_18192-2.png 5 +sketch/horse/n02374451_18192-3.png 5 +sketch/horse/n02374451_18192-4.png 5 +sketch/horse/n02374451_18192-5.png 5 +sketch/horse/n02374451_18192-6.png 5 +sketch/horse/n02374451_18570-1.png 5 +sketch/horse/n02374451_18570-2.png 5 +sketch/horse/n02374451_18570-3.png 5 +sketch/horse/n02374451_18570-4.png 5 +sketch/horse/n02374451_18570-5.png 5 +sketch/horse/n02374451_18570-6.png 5 +sketch/horse/n02374451_18570-7.png 5 +sketch/horse/n02374451_18909-1.png 5 +sketch/horse/n02374451_18909-2.png 5 +sketch/horse/n02374451_18909-3.png 5 +sketch/horse/n02374451_18909-4.png 5 +sketch/horse/n02374451_18909-5.png 5 +sketch/horse/n02374451_18909-6.png 5 +sketch/horse/8481.png 5 +sketch/horse/8482.png 5 +sketch/horse/8483.png 5 +sketch/horse/8484.png 5 +sketch/horse/8485.png 5 +sketch/horse/8486.png 5 +sketch/horse/8487.png 5 +sketch/horse/8488.png 5 +sketch/horse/8489.png 5 +sketch/horse/8490.png 5 +sketch/horse/8491.png 5 +sketch/horse/8492.png 5 +sketch/horse/8493.png 5 +sketch/horse/8494.png 5 +sketch/horse/8495.png 5 +sketch/horse/8496.png 5 +sketch/horse/8497.png 5 +sketch/horse/8498.png 5 +sketch/horse/8499.png 5 +sketch/horse/8500.png 5 +sketch/horse/8501.png 5 +sketch/horse/8502.png 5 +sketch/horse/8503.png 5 +sketch/horse/8504.png 5 +sketch/horse/8505.png 5 +sketch/horse/8506.png 5 +sketch/horse/8507.png 5 +sketch/horse/8508.png 5 +sketch/horse/8509.png 5 +sketch/horse/8510.png 5 +sketch/horse/8511.png 5 +sketch/horse/8512.png 5 +sketch/horse/8513.png 5 +sketch/horse/8514.png 5 +sketch/horse/8515.png 5 +sketch/horse/8516.png 5 +sketch/horse/8517.png 5 +sketch/horse/8518.png 5 +sketch/horse/8519.png 5 +sketch/horse/8520.png 5 +sketch/horse/8521.png 5 +sketch/horse/8522.png 5 +sketch/horse/8523.png 5 +sketch/horse/8524.png 5 +sketch/horse/8525.png 5 +sketch/horse/8526.png 5 +sketch/horse/8527.png 5 +sketch/horse/8528.png 5 +sketch/horse/8529.png 5 +sketch/horse/8530.png 5 +sketch/horse/8531.png 5 +sketch/horse/8532.png 5 +sketch/horse/8533.png 5 +sketch/horse/8534.png 5 +sketch/horse/8535.png 5 +sketch/horse/8536.png 5 +sketch/horse/8537.png 5 +sketch/horse/8538.png 5 +sketch/horse/8539.png 5 +sketch/horse/8540.png 5 +sketch/horse/8541.png 5 +sketch/horse/8542.png 5 +sketch/horse/8543.png 5 +sketch/horse/8544.png 5 +sketch/horse/8545.png 5 +sketch/horse/8546.png 5 +sketch/horse/8547.png 5 +sketch/horse/8548.png 5 +sketch/horse/8549.png 5 +sketch/horse/8550.png 5 +sketch/horse/8551.png 5 +sketch/horse/8552.png 5 +sketch/horse/8553.png 5 +sketch/horse/8554.png 5 +sketch/horse/8555.png 5 +sketch/horse/8556.png 5 +sketch/horse/8557.png 5 +sketch/horse/8558.png 5 +sketch/horse/8559.png 5 +sketch/horse/8560.png 5 +sketch/house/8801.png 6 +sketch/house/8802.png 6 +sketch/house/8803.png 6 +sketch/house/8804.png 6 +sketch/house/8805.png 6 +sketch/house/8806.png 6 +sketch/house/8807.png 6 +sketch/house/8808.png 6 +sketch/house/8809.png 6 +sketch/house/8810.png 6 +sketch/house/8811.png 6 +sketch/house/8812.png 6 +sketch/house/8813.png 6 +sketch/house/8814.png 6 +sketch/house/8815.png 6 +sketch/house/8816.png 6 +sketch/house/8817.png 6 +sketch/house/8818.png 6 +sketch/house/8819.png 6 +sketch/house/8820.png 6 +sketch/house/8821.png 6 +sketch/house/8822.png 6 +sketch/house/8823.png 6 +sketch/house/8824.png 6 +sketch/house/8825.png 6 +sketch/house/8826.png 6 +sketch/house/8827.png 6 +sketch/house/8828.png 6 +sketch/house/8829.png 6 +sketch/house/8830.png 6 +sketch/house/8831.png 6 +sketch/house/8832.png 6 +sketch/house/8833.png 6 +sketch/house/8834.png 6 +sketch/house/8835.png 6 +sketch/house/8836.png 6 +sketch/house/8837.png 6 +sketch/house/8838.png 6 +sketch/house/8839.png 6 +sketch/house/8840.png 6 +sketch/house/8841.png 6 +sketch/house/8842.png 6 +sketch/house/8843.png 6 +sketch/house/8844.png 6 +sketch/house/8845.png 6 +sketch/house/8846.png 6 +sketch/house/8847.png 6 +sketch/house/8848.png 6 +sketch/house/8849.png 6 +sketch/house/8850.png 6 +sketch/house/8851.png 6 +sketch/house/8852.png 6 +sketch/house/8853.png 6 +sketch/house/8854.png 6 +sketch/house/8855.png 6 +sketch/house/8856.png 6 +sketch/house/8857.png 6 +sketch/house/8858.png 6 +sketch/house/8859.png 6 +sketch/house/8860.png 6 +sketch/house/8861.png 6 +sketch/house/8862.png 6 +sketch/house/8863.png 6 +sketch/house/8864.png 6 +sketch/house/8865.png 6 +sketch/house/8866.png 6 +sketch/house/8867.png 6 +sketch/house/8868.png 6 +sketch/house/8869.png 6 +sketch/house/8870.png 6 +sketch/house/8871.png 6 +sketch/house/8872.png 6 +sketch/house/8873.png 6 +sketch/house/8874.png 6 +sketch/house/8875.png 6 +sketch/house/8876.png 6 +sketch/house/8877.png 6 +sketch/house/8878.png 6 +sketch/house/8879.png 6 +sketch/house/8880.png 6 +sketch/person/12081.png 7 +sketch/person/12082.png 7 +sketch/person/12083.png 7 +sketch/person/12084.png 7 +sketch/person/12085.png 7 +sketch/person/12086.png 7 +sketch/person/12087.png 7 +sketch/person/12088.png 7 +sketch/person/12089.png 7 +sketch/person/12090.png 7 +sketch/person/12091.png 7 +sketch/person/12092.png 7 +sketch/person/12093.png 7 +sketch/person/12094.png 7 +sketch/person/12095.png 7 +sketch/person/12096.png 7 +sketch/person/12097.png 7 +sketch/person/12098.png 7 +sketch/person/12099.png 7 +sketch/person/12100.png 7 +sketch/person/12101.png 7 +sketch/person/12102.png 7 +sketch/person/12103.png 7 +sketch/person/12104.png 7 +sketch/person/12105.png 7 +sketch/person/12106.png 7 +sketch/person/12107.png 7 +sketch/person/12108.png 7 +sketch/person/12109.png 7 +sketch/person/12110.png 7 +sketch/person/12111.png 7 +sketch/person/12112.png 7 +sketch/person/12113.png 7 +sketch/person/12114.png 7 +sketch/person/12115.png 7 +sketch/person/12116.png 7 +sketch/person/12117.png 7 +sketch/person/12118.png 7 +sketch/person/12119.png 7 +sketch/person/12120.png 7 +sketch/person/12121.png 7 +sketch/person/12122.png 7 +sketch/person/12123.png 7 +sketch/person/12124.png 7 +sketch/person/12125.png 7 +sketch/person/12126.png 7 +sketch/person/12127.png 7 +sketch/person/12128.png 7 +sketch/person/12129.png 7 +sketch/person/12130.png 7 +sketch/person/12131.png 7 +sketch/person/12132.png 7 +sketch/person/12133.png 7 +sketch/person/12134.png 7 +sketch/person/12135.png 7 +sketch/person/12136.png 7 +sketch/person/12137.png 7 +sketch/person/12138.png 7 +sketch/person/12139.png 7 +sketch/person/12140.png 7 +sketch/person/12141.png 7 +sketch/person/12142.png 7 +sketch/person/12143.png 7 +sketch/person/12144.png 7 +sketch/person/12145.png 7 +sketch/person/12146.png 7 +sketch/person/12147.png 7 +sketch/person/12148.png 7 +sketch/person/12149.png 7 +sketch/person/12150.png 7 +sketch/person/12151.png 7 +sketch/person/12152.png 7 +sketch/person/12153.png 7 +sketch/person/12154.png 7 +sketch/person/12155.png 7 +sketch/person/12156.png 7 +sketch/person/12157.png 7 +sketch/person/12158.png 7 +sketch/person/12159.png 7 +sketch/person/12160.png 7 +sketch/person/12161.png 7 +sketch/person/12162.png 7 +sketch/person/12163.png 7 +sketch/person/12164.png 7 +sketch/person/12165.png 7 +sketch/person/12166.png 7 +sketch/person/12167.png 7 +sketch/person/12168.png 7 +sketch/person/12169.png 7 +sketch/person/12170.png 7 +sketch/person/12171.png 7 +sketch/person/12172.png 7 +sketch/person/12173.png 7 +sketch/person/12174.png 7 +sketch/person/12175.png 7 +sketch/person/12176.png 7 +sketch/person/12177.png 7 +sketch/person/12178.png 7 +sketch/person/12179.png 7 +sketch/person/12180.png 7 +sketch/person/12181.png 7 +sketch/person/12182.png 7 +sketch/person/12183.png 7 +sketch/person/12184.png 7 +sketch/person/12185.png 7 +sketch/person/12186.png 7 +sketch/person/12187.png 7 +sketch/person/12188.png 7 +sketch/person/12189.png 7 +sketch/person/12190.png 7 +sketch/person/12191.png 7 +sketch/person/12192.png 7 +sketch/person/12193.png 7 +sketch/person/12194.png 7 +sketch/person/12195.png 7 +sketch/person/12196.png 7 +sketch/person/12197.png 7 +sketch/person/12198.png 7 +sketch/person/12199.png 7 +sketch/person/12200.png 7 +sketch/person/12201.png 7 +sketch/person/12202.png 7 +sketch/person/12203.png 7 +sketch/person/12204.png 7 +sketch/person/12205.png 7 +sketch/person/12206.png 7 +sketch/person/12207.png 7 +sketch/person/12208.png 7 +sketch/person/12209.png 7 +sketch/person/12210.png 7 +sketch/person/12211.png 7 +sketch/person/12212.png 7 +sketch/person/12213.png 7 +sketch/person/12214.png 7 +sketch/person/12215.png 7 +sketch/person/12216.png 7 +sketch/person/12217.png 7 +sketch/person/12218.png 7 +sketch/person/12219.png 7 +sketch/person/12220.png 7 +sketch/person/12221.png 7 +sketch/person/12222.png 7 +sketch/person/12223.png 7 +sketch/person/12224.png 7 +sketch/person/12225.png 7 +sketch/person/12226.png 7 +sketch/person/12227.png 7 +sketch/person/12228.png 7 +sketch/person/12229.png 7 +sketch/person/12230.png 7 +sketch/person/12231.png 7 +sketch/person/12232.png 7 +sketch/person/12233.png 7 +sketch/person/12234.png 7 +sketch/person/12235.png 7 +sketch/person/12236.png 7 +sketch/person/12237.png 7 +sketch/person/12238.png 7 +sketch/person/12239.png 7 +sketch/person/12240.png 7 diff --git a/domainlab/zdata/pacs_split/sketch_train_kfold.txt b/domainlab/zdata/pacs_split/sketch_train_kfold.txt new file mode 100644 index 000000000..a5088dca0 --- /dev/null +++ b/domainlab/zdata/pacs_split/sketch_train_kfold.txt @@ -0,0 +1,3531 @@ +sketch/dog/n02103406_1170-6.png 1 +sketch/dog/n02103406_1247-1.png 1 +sketch/dog/n02103406_1247-2.png 1 +sketch/dog/n02103406_1247-3.png 1 +sketch/dog/n02103406_1247-4.png 1 +sketch/dog/n02103406_1247-5.png 1 +sketch/dog/n02103406_1247-6.png 1 +sketch/dog/n02103406_1247-7.png 1 +sketch/dog/n02103406_1599-1.png 1 +sketch/dog/n02103406_1599-2.png 1 +sketch/dog/n02103406_1599-3.png 1 +sketch/dog/n02103406_1599-4.png 1 +sketch/dog/n02103406_1599-5.png 1 +sketch/dog/n02103406_1754-1.png 1 +sketch/dog/n02103406_1754-2.png 1 +sketch/dog/n02103406_1754-3.png 1 +sketch/dog/n02103406_1754-4.png 1 +sketch/dog/n02103406_1754-5.png 1 +sketch/dog/n02103406_2209-1.png 1 +sketch/dog/n02103406_2209-2.png 1 +sketch/dog/n02103406_2209-3.png 1 +sketch/dog/n02103406_2209-4.png 1 +sketch/dog/n02103406_2209-5.png 1 +sketch/dog/n02103406_2209-6.png 1 +sketch/dog/n02103406_2209-7.png 1 +sketch/dog/n02103406_2209-8.png 1 +sketch/dog/n02103406_2706-1.png 1 +sketch/dog/n02103406_2706-2.png 1 +sketch/dog/n02103406_2706-3.png 1 +sketch/dog/n02103406_2706-4.png 1 +sketch/dog/n02103406_2706-5.png 1 +sketch/dog/n02103406_2706-6.png 1 +sketch/dog/n02103406_2706-7.png 1 +sketch/dog/n02103406_2706-8.png 1 +sketch/dog/n02103406_2706-9.png 1 +sketch/dog/n02103406_2954-1.png 1 +sketch/dog/n02103406_2954-2.png 1 +sketch/dog/n02103406_2954-3.png 1 +sketch/dog/n02103406_2954-4.png 1 +sketch/dog/n02103406_2954-5.png 1 +sketch/dog/n02103406_2954-6.png 1 +sketch/dog/n02103406_2976-1.png 1 +sketch/dog/n02103406_2976-2.png 1 +sketch/dog/n02103406_2976-3.png 1 +sketch/dog/n02103406_2976-4.png 1 +sketch/dog/n02103406_2976-5.png 1 +sketch/dog/n02103406_2976-6.png 1 +sketch/dog/n02103406_2976-7.png 1 +sketch/dog/n02103406_3056-1.png 1 +sketch/dog/n02103406_3056-2.png 1 +sketch/dog/n02103406_3056-3.png 1 +sketch/dog/n02103406_3056-4.png 1 +sketch/dog/n02103406_3056-5.png 1 +sketch/dog/n02103406_3108-1.png 1 +sketch/dog/n02103406_3108-2.png 1 +sketch/dog/n02103406_3108-3.png 1 +sketch/dog/n02103406_3108-4.png 1 +sketch/dog/n02103406_3108-5.png 1 +sketch/dog/n02103406_3108-6.png 1 +sketch/dog/n02103406_3132-1.png 1 +sketch/dog/n02103406_3132-2.png 1 +sketch/dog/n02103406_3132-3.png 1 +sketch/dog/n02103406_3132-4.png 1 +sketch/dog/n02103406_3132-5.png 1 +sketch/dog/n02103406_3132-6.png 1 +sketch/dog/n02103406_3132-7.png 1 +sketch/dog/n02103406_3255-1.png 1 +sketch/dog/n02103406_3255-2.png 1 +sketch/dog/n02103406_3255-3.png 1 +sketch/dog/n02103406_3255-4.png 1 +sketch/dog/n02103406_3255-5.png 1 +sketch/dog/n02103406_3255-6.png 1 +sketch/dog/n02103406_3255-7.png 1 +sketch/dog/n02103406_3255-8.png 1 +sketch/dog/n02103406_3255-9.png 1 +sketch/dog/n02103406_3255-10.png 1 +sketch/dog/n02103406_3255-11.png 1 +sketch/dog/n02103406_3299-1.png 1 +sketch/dog/n02103406_3299-2.png 1 +sketch/dog/n02103406_3299-3.png 1 +sketch/dog/n02103406_3299-4.png 1 +sketch/dog/n02103406_3299-5.png 1 +sketch/dog/n02103406_3299-6.png 1 +sketch/dog/n02103406_3299-7.png 1 +sketch/dog/n02103406_3299-8.png 1 +sketch/dog/n02103406_3299-9.png 1 +sketch/dog/n02103406_3326-1.png 1 +sketch/dog/n02103406_3326-2.png 1 +sketch/dog/n02103406_3326-3.png 1 +sketch/dog/n02103406_3326-4.png 1 +sketch/dog/n02103406_3326-5.png 1 +sketch/dog/n02103406_3326-6.png 1 +sketch/dog/n02103406_3326-7.png 1 +sketch/dog/n02103406_3326-8.png 1 +sketch/dog/n02103406_3326-9.png 1 +sketch/dog/n02103406_3326-10.png 1 +sketch/dog/n02103406_3326-11.png 1 +sketch/dog/n02103406_3326-12.png 1 +sketch/dog/n02103406_3326-13.png 1 +sketch/dog/n02103406_3401-1.png 1 +sketch/dog/n02103406_3401-2.png 1 +sketch/dog/n02103406_3401-3.png 1 +sketch/dog/n02103406_3401-4.png 1 +sketch/dog/n02103406_3401-5.png 1 +sketch/dog/n02103406_3401-6.png 1 +sketch/dog/n02103406_3538-1.png 1 +sketch/dog/n02103406_3538-2.png 1 +sketch/dog/n02103406_3538-3.png 1 +sketch/dog/n02103406_3538-4.png 1 +sketch/dog/n02103406_3538-5.png 1 +sketch/dog/n02103406_3538-6.png 1 +sketch/dog/n02103406_3538-7.png 1 +sketch/dog/n02103406_3743-1.png 1 +sketch/dog/n02103406_3743-2.png 1 +sketch/dog/n02103406_3743-3.png 1 +sketch/dog/n02103406_3743-4.png 1 +sketch/dog/n02103406_3743-5.png 1 +sketch/dog/n02103406_3743-6.png 1 +sketch/dog/n02103406_3743-7.png 1 +sketch/dog/n02103406_3743-8.png 1 +sketch/dog/n02103406_3743-9.png 1 +sketch/dog/n02103406_3743-10.png 1 +sketch/dog/n02103406_3750-1.png 1 +sketch/dog/n02103406_3750-2.png 1 +sketch/dog/n02103406_3750-3.png 1 +sketch/dog/n02103406_3750-4.png 1 +sketch/dog/n02103406_3750-5.png 1 +sketch/dog/n02103406_3750-6.png 1 +sketch/dog/n02103406_3964-1.png 1 +sketch/dog/n02103406_3964-2.png 1 +sketch/dog/n02103406_3964-3.png 1 +sketch/dog/n02103406_3964-4.png 1 +sketch/dog/n02103406_3964-5.png 1 +sketch/dog/n02103406_4068-1.png 1 +sketch/dog/n02103406_4068-2.png 1 +sketch/dog/n02103406_4068-3.png 1 +sketch/dog/n02103406_4068-4.png 1 +sketch/dog/n02103406_4068-5.png 1 +sketch/dog/n02103406_4068-6.png 1 +sketch/dog/n02103406_4068-7.png 1 +sketch/dog/n02103406_4068-8.png 1 +sketch/dog/n02103406_4068-9.png 1 +sketch/dog/n02103406_4068-10.png 1 +sketch/dog/n02103406_4068-11.png 1 +sketch/dog/n02103406_4068-12.png 1 +sketch/dog/n02103406_4582-1.png 1 +sketch/dog/n02103406_4582-2.png 1 +sketch/dog/n02103406_4582-3.png 1 +sketch/dog/n02103406_4582-4.png 1 +sketch/dog/n02103406_4582-5.png 1 +sketch/dog/n02103406_4849-1.png 1 +sketch/dog/n02103406_4849-2.png 1 +sketch/dog/n02103406_4849-3.png 1 +sketch/dog/n02103406_4849-4.png 1 +sketch/dog/n02103406_4849-5.png 1 +sketch/dog/n02103406_4849-6.png 1 +sketch/dog/n02103406_4849-7.png 1 +sketch/dog/n02103406_4849-8.png 1 +sketch/dog/n02103406_4849-9.png 1 +sketch/dog/n02103406_4916-1.png 1 +sketch/dog/n02103406_4916-2.png 1 +sketch/dog/n02103406_4916-3.png 1 +sketch/dog/n02103406_4916-4.png 1 +sketch/dog/n02103406_4916-5.png 1 +sketch/dog/n02103406_5035-1.png 1 +sketch/dog/n02103406_5035-2.png 1 +sketch/dog/n02103406_5035-3.png 1 +sketch/dog/n02103406_5035-4.png 1 +sketch/dog/n02103406_5035-5.png 1 +sketch/dog/n02103406_5035-6.png 1 +sketch/dog/n02103406_5216-1.png 1 +sketch/dog/n02103406_5216-2.png 1 +sketch/dog/n02103406_5216-3.png 1 +sketch/dog/n02103406_5216-4.png 1 +sketch/dog/n02103406_5216-5.png 1 +sketch/dog/n02103406_5224-1.png 1 +sketch/dog/n02103406_5224-2.png 1 +sketch/dog/n02103406_5224-3.png 1 +sketch/dog/n02103406_5224-4.png 1 +sketch/dog/n02103406_5224-5.png 1 +sketch/dog/n02103406_5224-6.png 1 +sketch/dog/n02103406_5456-1.png 1 +sketch/dog/n02103406_5456-2.png 1 +sketch/dog/n02103406_5456-3.png 1 +sketch/dog/n02103406_5456-4.png 1 +sketch/dog/n02103406_5456-5.png 1 +sketch/dog/n02103406_5456-6.png 1 +sketch/dog/n02103406_5456-7.png 1 +sketch/dog/n02103406_5456-8.png 1 +sketch/dog/n02103406_5456-9.png 1 +sketch/dog/n02103406_5505-1.png 1 +sketch/dog/n02103406_5505-2.png 1 +sketch/dog/n02103406_5505-3.png 1 +sketch/dog/n02103406_5505-4.png 1 +sketch/dog/n02103406_5505-5.png 1 +sketch/dog/n02103406_5505-6.png 1 +sketch/dog/n02103406_5563-1.png 1 +sketch/dog/n02103406_5563-2.png 1 +sketch/dog/n02103406_5563-3.png 1 +sketch/dog/n02103406_5563-4.png 1 +sketch/dog/n02103406_5563-5.png 1 +sketch/dog/n02103406_5563-6.png 1 +sketch/dog/n02103406_5563-7.png 1 +sketch/dog/n02103406_5601-1.png 1 +sketch/dog/n02103406_5601-2.png 1 +sketch/dog/n02103406_5601-3.png 1 +sketch/dog/n02103406_5601-4.png 1 +sketch/dog/n02103406_5601-5.png 1 +sketch/dog/n02103406_5601-6.png 1 +sketch/dog/n02103406_6274-1.png 1 +sketch/dog/n02103406_6274-2.png 1 +sketch/dog/n02103406_6274-3.png 1 +sketch/dog/n02103406_6274-4.png 1 +sketch/dog/n02103406_6274-5.png 1 +sketch/dog/n02103406_6461-1.png 1 +sketch/dog/n02103406_6461-2.png 1 +sketch/dog/n02103406_6461-3.png 1 +sketch/dog/n02103406_6461-4.png 1 +sketch/dog/n02103406_6461-5.png 1 +sketch/dog/n02103406_6461-6.png 1 +sketch/dog/n02103406_6461-7.png 1 +sketch/dog/n02103406_6530-1.png 1 +sketch/dog/n02103406_6530-2.png 1 +sketch/dog/n02103406_6530-3.png 1 +sketch/dog/n02103406_6530-4.png 1 +sketch/dog/n02103406_6530-5.png 1 +sketch/dog/n02103406_6530-6.png 1 +sketch/dog/n02103406_6530-7.png 1 +sketch/dog/n02103406_6688-1.png 1 +sketch/dog/n02103406_6688-2.png 1 +sketch/dog/n02103406_6688-3.png 1 +sketch/dog/n02103406_6688-4.png 1 +sketch/dog/n02103406_6688-5.png 1 +sketch/dog/n02103406_6688-6.png 1 +sketch/dog/n02103406_6688-7.png 1 +sketch/dog/n02103406_6688-8.png 1 +sketch/dog/n02103406_6688-9.png 1 +sketch/dog/n02103406_6852-1.png 1 +sketch/dog/n02103406_6852-2.png 1 +sketch/dog/n02103406_6852-3.png 1 +sketch/dog/n02103406_6852-4.png 1 +sketch/dog/n02103406_6852-5.png 1 +sketch/dog/n02103406_6852-6.png 1 +sketch/dog/n02103406_6852-7.png 1 +sketch/dog/n02103406_6852-8.png 1 +sketch/dog/n02103406_6852-9.png 1 +sketch/dog/n02103406_6857-1.png 1 +sketch/dog/n02103406_6857-2.png 1 +sketch/dog/n02103406_6857-3.png 1 +sketch/dog/n02103406_6857-4.png 1 +sketch/dog/n02103406_6857-5.png 1 +sketch/dog/n02103406_6857-6.png 1 +sketch/dog/n02103406_6857-7.png 1 +sketch/dog/n02103406_6857-8.png 1 +sketch/dog/n02103406_7201-1.png 1 +sketch/dog/n02103406_7201-2.png 1 +sketch/dog/n02103406_7201-3.png 1 +sketch/dog/n02103406_7201-4.png 1 +sketch/dog/n02103406_7201-5.png 1 +sketch/dog/n02103406_7201-6.png 1 +sketch/dog/n02103406_7368-1.png 1 +sketch/dog/n02103406_7368-2.png 1 +sketch/dog/n02103406_7368-3.png 1 +sketch/dog/n02103406_7368-4.png 1 +sketch/dog/n02103406_7368-5.png 1 +sketch/dog/n02103406_7368-6.png 1 +sketch/dog/n02103406_7368-7.png 1 +sketch/dog/n02103406_7368-8.png 1 +sketch/dog/n02103406_7368-9.png 1 +sketch/dog/n02103406_7368-10.png 1 +sketch/dog/n02103406_7521-1.png 1 +sketch/dog/n02103406_7521-2.png 1 +sketch/dog/n02103406_7521-3.png 1 +sketch/dog/n02103406_7521-4.png 1 +sketch/dog/n02103406_7521-5.png 1 +sketch/dog/n02103406_7521-6.png 1 +sketch/dog/n02103406_7521-7.png 1 +sketch/dog/n02103406_7521-8.png 1 +sketch/dog/n02103406_7708-1.png 1 +sketch/dog/n02103406_7708-2.png 1 +sketch/dog/n02103406_7708-3.png 1 +sketch/dog/n02103406_7708-4.png 1 +sketch/dog/n02103406_7708-5.png 1 +sketch/dog/n02103406_7708-6.png 1 +sketch/dog/n02103406_7708-7.png 1 +sketch/dog/n02103406_7708-8.png 1 +sketch/dog/n02103406_7708-9.png 1 +sketch/dog/n02103406_7708-10.png 1 +sketch/dog/n02103406_8004-1.png 1 +sketch/dog/n02103406_8004-2.png 1 +sketch/dog/n02103406_8004-3.png 1 +sketch/dog/n02103406_8004-4.png 1 +sketch/dog/n02103406_8004-5.png 1 +sketch/dog/n02103406_8004-6.png 1 +sketch/dog/n02103406_8004-7.png 1 +sketch/dog/n02103406_8004-8.png 1 +sketch/dog/n02103406_8004-9.png 1 +sketch/dog/n02103406_8280-1.png 1 +sketch/dog/n02103406_8280-2.png 1 +sketch/dog/n02103406_8280-3.png 1 +sketch/dog/n02103406_8280-4.png 1 +sketch/dog/n02103406_8280-5.png 1 +sketch/dog/n02103406_8280-6.png 1 +sketch/dog/n02103406_8362-1.png 1 +sketch/dog/n02103406_8362-2.png 1 +sketch/dog/n02103406_8362-3.png 1 +sketch/dog/n02103406_8362-4.png 1 +sketch/dog/n02103406_8362-5.png 1 +sketch/dog/n02103406_8362-6.png 1 +sketch/dog/n02103406_8362-7.png 1 +sketch/dog/n02103406_8362-8.png 1 +sketch/dog/n02103406_8362-9.png 1 +sketch/dog/n02103406_8362-10.png 1 +sketch/dog/n02103406_8421-1.png 1 +sketch/dog/n02103406_8421-2.png 1 +sketch/dog/n02103406_8421-3.png 1 +sketch/dog/n02103406_8421-4.png 1 +sketch/dog/n02103406_8421-5.png 1 +sketch/dog/n02103406_8421-6.png 1 +sketch/dog/n02103406_13049-1.png 1 +sketch/dog/n02103406_13049-2.png 1 +sketch/dog/n02103406_13049-3.png 1 +sketch/dog/n02103406_13049-4.png 1 +sketch/dog/n02103406_13049-5.png 1 +sketch/dog/n02103406_13049-6.png 1 +sketch/dog/n02106662_466-1.png 1 +sketch/dog/n02106662_466-2.png 1 +sketch/dog/n02106662_466-3.png 1 +sketch/dog/n02106662_466-4.png 1 +sketch/dog/n02106662_466-5.png 1 +sketch/dog/n02106662_466-6.png 1 +sketch/dog/n02106662_466-7.png 1 +sketch/dog/n02106662_928-1.png 1 +sketch/dog/n02106662_928-2.png 1 +sketch/dog/n02106662_928-3.png 1 +sketch/dog/n02106662_928-4.png 1 +sketch/dog/n02106662_928-5.png 1 +sketch/dog/n02106662_928-6.png 1 +sketch/dog/n02106662_928-7.png 1 +sketch/dog/n02106662_928-8.png 1 +sketch/dog/n02106662_928-9.png 1 +sketch/dog/n02106662_928-10.png 1 +sketch/dog/n02106662_928-11.png 1 +sketch/dog/n02106662_1874-1.png 1 +sketch/dog/n02106662_1874-2.png 1 +sketch/dog/n02106662_1874-3.png 1 +sketch/dog/n02106662_1874-4.png 1 +sketch/dog/n02106662_1874-5.png 1 +sketch/dog/n02106662_1922-1.png 1 +sketch/dog/n02106662_1922-2.png 1 +sketch/dog/n02106662_1922-3.png 1 +sketch/dog/n02106662_1922-4.png 1 +sketch/dog/n02106662_1922-5.png 1 +sketch/dog/n02106662_2101-1.png 1 +sketch/dog/n02106662_2101-2.png 1 +sketch/dog/n02106662_2101-3.png 1 +sketch/dog/n02106662_2101-4.png 1 +sketch/dog/n02106662_2101-5.png 1 +sketch/dog/n02106662_2101-6.png 1 +sketch/dog/n02106662_2101-7.png 1 +sketch/dog/n02106662_2101-8.png 1 +sketch/dog/n02106662_2101-9.png 1 +sketch/dog/n02106662_2157-1.png 1 +sketch/dog/n02106662_2157-2.png 1 +sketch/dog/n02106662_2157-3.png 1 +sketch/dog/n02106662_2157-4.png 1 +sketch/dog/n02106662_2157-5.png 1 +sketch/dog/n02106662_2157-6.png 1 +sketch/dog/n02106662_2377-1.png 1 +sketch/dog/n02106662_2377-2.png 1 +sketch/dog/n02106662_2377-3.png 1 +sketch/dog/n02106662_2377-4.png 1 +sketch/dog/n02106662_2377-5.png 1 +sketch/dog/n02106662_2377-6.png 1 +sketch/dog/n02106662_2740-1.png 1 +sketch/dog/n02106662_2740-2.png 1 +sketch/dog/n02106662_2740-3.png 1 +sketch/dog/n02106662_2740-4.png 1 +sketch/dog/n02106662_2740-5.png 1 +sketch/dog/n02106662_5001-1.png 1 +sketch/dog/n02106662_5001-2.png 1 +sketch/dog/n02106662_5001-3.png 1 +sketch/dog/n02106662_5001-4.png 1 +sketch/dog/n02106662_5001-5.png 1 +sketch/dog/n02106662_5001-6.png 1 +sketch/dog/n02106662_5001-7.png 1 +sketch/dog/n02106662_7885-1.png 1 +sketch/dog/n02106662_7885-2.png 1 +sketch/dog/n02106662_7885-3.png 1 +sketch/dog/n02106662_7885-4.png 1 +sketch/dog/n02106662_7885-5.png 1 +sketch/dog/n02106662_7960-1.png 1 +sketch/dog/n02106662_7960-2.png 1 +sketch/dog/n02106662_7960-3.png 1 +sketch/dog/n02106662_7960-4.png 1 +sketch/dog/n02106662_7960-5.png 1 +sketch/dog/n02106662_7960-6.png 1 +sketch/dog/n02106662_8511-1.png 1 +sketch/dog/n02106662_8511-2.png 1 +sketch/dog/n02106662_8511-3.png 1 +sketch/dog/n02106662_8511-4.png 1 +sketch/dog/n02106662_8511-5.png 1 +sketch/dog/n02106662_8511-6.png 1 +sketch/dog/n02106662_8870-1.png 1 +sketch/dog/n02106662_8870-2.png 1 +sketch/dog/n02106662_8870-3.png 1 +sketch/dog/n02106662_8870-4.png 1 +sketch/dog/n02106662_8870-5.png 1 +sketch/dog/n02106662_8870-6.png 1 +sketch/dog/n02106662_8870-7.png 1 +sketch/dog/n02106662_10406-1.png 1 +sketch/dog/n02106662_10406-2.png 1 +sketch/dog/n02106662_10406-3.png 1 +sketch/dog/n02106662_10406-4.png 1 +sketch/dog/n02106662_10406-5.png 1 +sketch/dog/n02106662_10406-6.png 1 +sketch/dog/n02106662_11133-1.png 1 +sketch/dog/n02106662_11133-2.png 1 +sketch/dog/n02106662_11133-3.png 1 +sketch/dog/n02106662_11133-4.png 1 +sketch/dog/n02106662_11133-5.png 1 +sketch/dog/n02106662_13178-1.png 1 +sketch/dog/n02106662_13178-2.png 1 +sketch/dog/n02106662_13178-3.png 1 +sketch/dog/n02106662_13178-4.png 1 +sketch/dog/n02106662_13178-5.png 1 +sketch/dog/n02106662_13912-1.png 1 +sketch/dog/n02106662_13912-2.png 1 +sketch/dog/n02106662_13912-3.png 1 +sketch/dog/n02106662_13912-4.png 1 +sketch/dog/n02106662_13912-5.png 1 +sketch/dog/n02106662_15858-1.png 1 +sketch/dog/n02106662_15858-2.png 1 +sketch/dog/n02106662_15858-3.png 1 +sketch/dog/n02106662_15858-4.png 1 +sketch/dog/n02106662_15858-5.png 1 +sketch/dog/n02106662_15858-6.png 1 +sketch/dog/n02106662_18402-1.png 1 +sketch/dog/n02106662_18402-2.png 1 +sketch/dog/n02106662_18402-3.png 1 +sketch/dog/n02106662_18402-4.png 1 +sketch/dog/n02106662_18402-5.png 1 +sketch/dog/n02106662_18405-1.png 1 +sketch/dog/n02106662_18405-2.png 1 +sketch/dog/n02106662_18405-3.png 1 +sketch/dog/n02106662_18405-4.png 1 +sketch/dog/n02106662_18405-5.png 1 +sketch/dog/n02106662_18922-1.png 1 +sketch/dog/n02106662_18922-2.png 1 +sketch/dog/n02106662_18922-3.png 1 +sketch/dog/n02106662_18922-4.png 1 +sketch/dog/n02106662_18922-5.png 1 +sketch/dog/n02106662_18922-6.png 1 +sketch/dog/n02106662_18922-7.png 1 +sketch/dog/n02106662_18922-8.png 1 +sketch/dog/n02106662_18922-9.png 1 +sketch/dog/n02106662_18922-10.png 1 +sketch/dog/n02106662_18922-11.png 1 +sketch/dog/n02106662_18953-1.png 1 +sketch/dog/n02106662_18953-2.png 1 +sketch/dog/n02106662_18953-3.png 1 +sketch/dog/n02106662_18953-4.png 1 +sketch/dog/n02106662_18953-5.png 1 +sketch/dog/n02106662_18953-6.png 1 +sketch/dog/n02106662_18953-7.png 1 +sketch/dog/n02106662_24019-1.png 1 +sketch/dog/n02106662_24019-2.png 1 +sketch/dog/n02106662_24019-3.png 1 +sketch/dog/n02106662_24019-4.png 1 +sketch/dog/n02106662_24019-5.png 1 +sketch/dog/n02106662_24019-6.png 1 +sketch/dog/n02106662_24019-7.png 1 +sketch/dog/n02106662_24019-8.png 1 +sketch/dog/n02106662_24577-1.png 1 +sketch/dog/n02106662_24577-2.png 1 +sketch/dog/n02106662_24577-3.png 1 +sketch/dog/n02106662_24577-4.png 1 +sketch/dog/n02106662_24577-5.png 1 +sketch/dog/n02106662_24786-1.png 1 +sketch/dog/n02106662_24786-2.png 1 +sketch/dog/n02106662_24786-3.png 1 +sketch/dog/n02106662_24786-4.png 1 +sketch/dog/n02106662_24786-5.png 1 +sketch/dog/n02106662_24786-6.png 1 +sketch/dog/n02106662_24786-7.png 1 +sketch/dog/n02106662_25917-1.png 1 +sketch/dog/n02106662_25917-2.png 1 +sketch/dog/n02106662_25917-3.png 1 +sketch/dog/n02106662_25917-4.png 1 +sketch/dog/n02106662_25917-5.png 1 +sketch/dog/n02106662_25917-6.png 1 +sketch/dog/n02106662_25917-7.png 1 +sketch/dog/n02106662_26549-1.png 1 +sketch/dog/n02106662_26549-2.png 1 +sketch/dog/n02106662_26549-3.png 1 +sketch/dog/n02106662_26549-4.png 1 +sketch/dog/n02106662_26549-5.png 1 +sketch/dog/n02106662_26549-6.png 1 +sketch/dog/n02106662_27393-1.png 1 +sketch/dog/n02106662_27393-2.png 1 +sketch/dog/n02106662_27393-3.png 1 +sketch/dog/n02106662_27393-4.png 1 +sketch/dog/n02106662_27393-5.png 1 +sketch/dog/n02109525_704-1.png 1 +sketch/dog/n02109525_704-2.png 1 +sketch/dog/n02109525_704-3.png 1 +sketch/dog/n02109525_704-4.png 1 +sketch/dog/n02109525_704-5.png 1 +sketch/dog/n02109525_704-6.png 1 +sketch/dog/n02109525_1893-1.png 1 +sketch/dog/n02109525_1893-2.png 1 +sketch/dog/n02109525_1893-3.png 1 +sketch/dog/n02109525_1893-4.png 1 +sketch/dog/n02109525_1893-5.png 1 +sketch/dog/n02109525_1893-6.png 1 +sketch/dog/n02109525_1893-7.png 1 +sketch/dog/n02109525_3202-1.png 1 +sketch/dog/n02109525_3202-2.png 1 +sketch/dog/n02109525_3202-3.png 1 +sketch/dog/n02109525_3202-4.png 1 +sketch/dog/n02109525_3202-5.png 1 +sketch/dog/n02109525_3202-6.png 1 +sketch/dog/n02109525_3782-1.png 1 +sketch/dog/n02109525_3782-2.png 1 +sketch/dog/n02109525_3782-3.png 1 +sketch/dog/n02109525_3782-4.png 1 +sketch/dog/n02109525_3782-5.png 1 +sketch/dog/n02109525_3782-6.png 1 +sketch/dog/n02109525_3782-7.png 1 +sketch/dog/n02109525_3782-8.png 1 +sketch/dog/n02109525_3782-9.png 1 +sketch/dog/n02109525_3782-10.png 1 +sketch/dog/n02109525_5013-1.png 1 +sketch/dog/n02109525_5013-2.png 1 +sketch/dog/n02109525_5013-3.png 1 +sketch/dog/n02109525_5013-4.png 1 +sketch/dog/n02109525_5013-5.png 1 +sketch/dog/n02109525_5013-6.png 1 +sketch/dog/n02109525_5583-1.png 1 +sketch/dog/n02109525_5583-2.png 1 +sketch/dog/n02109525_5583-3.png 1 +sketch/dog/n02109525_5583-4.png 1 +sketch/dog/n02109525_5583-5.png 1 +sketch/dog/n02109525_5583-6.png 1 +sketch/dog/n02109525_5583-7.png 1 +sketch/dog/n02109525_5966-1.png 1 +sketch/dog/n02109525_5966-2.png 1 +sketch/dog/n02109525_5966-3.png 1 +sketch/dog/n02109525_5966-4.png 1 +sketch/dog/n02109525_5966-5.png 1 +sketch/dog/n02109525_6693-1.png 1 +sketch/dog/n02109525_6693-2.png 1 +sketch/dog/n02109525_6693-3.png 1 +sketch/dog/n02109525_6693-4.png 1 +sketch/dog/n02109525_6693-5.png 1 +sketch/dog/n02109525_7874-1.png 1 +sketch/dog/n02109525_7874-2.png 1 +sketch/dog/n02109525_7874-3.png 1 +sketch/dog/n02109525_7874-4.png 1 +sketch/dog/n02109525_7874-5.png 1 +sketch/dog/n02109525_7874-6.png 1 +sketch/dog/n02109525_8211-1.png 1 +sketch/dog/n02109525_8211-2.png 1 +sketch/dog/n02109525_8211-3.png 1 +sketch/dog/n02109525_8211-4.png 1 +sketch/dog/n02109525_8211-5.png 1 +sketch/dog/n02109525_8457-1.png 1 +sketch/dog/n02109525_8457-2.png 1 +sketch/dog/n02109525_8457-3.png 1 +sketch/dog/n02109525_8457-4.png 1 +sketch/dog/n02109525_8457-5.png 1 +sketch/dog/n02109525_9037-1.png 1 +sketch/dog/n02109525_9037-2.png 1 +sketch/dog/n02109525_9037-3.png 1 +sketch/dog/n02109525_9037-4.png 1 +sketch/dog/n02109525_9037-5.png 1 +sketch/dog/n02109525_9037-6.png 1 +sketch/dog/n02109525_9037-7.png 1 +sketch/dog/n02109525_10297-1.png 1 +sketch/dog/n02109525_10297-2.png 1 +sketch/dog/n02109525_10297-3.png 1 +sketch/dog/n02109525_10297-4.png 1 +sketch/dog/n02109525_10297-5.png 1 +sketch/dog/n02109525_11444-1.png 1 +sketch/dog/n02109525_11444-2.png 1 +sketch/dog/n02109525_11444-3.png 1 +sketch/dog/n02109525_11444-4.png 1 +sketch/dog/n02109525_11444-5.png 1 +sketch/dog/n02109525_12875-1.png 1 +sketch/dog/n02109525_12875-2.png 1 +sketch/dog/n02109525_12875-3.png 1 +sketch/dog/n02109525_12875-4.png 1 +sketch/dog/n02109525_12875-5.png 1 +sketch/dog/n02109525_12875-6.png 1 +sketch/dog/n02109525_13700-1.png 1 +sketch/dog/n02109525_13700-2.png 1 +sketch/dog/n02109525_13700-3.png 1 +sketch/dog/n02109525_13700-4.png 1 +sketch/dog/n02109525_13700-5.png 1 +sketch/dog/n02109525_16346-1.png 1 +sketch/dog/n02109525_16346-2.png 1 +sketch/dog/n02109525_16346-3.png 1 +sketch/dog/n02109525_16346-4.png 1 +sketch/dog/n02109525_16346-5.png 1 +sketch/dog/n02109525_16346-6.png 1 +sketch/dog/n02109525_16346-7.png 1 +sketch/dog/n02109525_16346-8.png 1 +sketch/dog/n02109525_18347-1.png 1 +sketch/dog/n02109525_18347-2.png 1 +sketch/dog/n02109525_18347-3.png 1 +sketch/dog/n02109525_18347-4.png 1 +sketch/dog/n02109525_18347-5.png 1 +sketch/dog/n02109525_18347-6.png 1 +sketch/dog/n02109525_18347-7.png 1 +sketch/dog/5281.png 1 +sketch/dog/5282.png 1 +sketch/dog/5283.png 1 +sketch/dog/5284.png 1 +sketch/dog/5285.png 1 +sketch/dog/5286.png 1 +sketch/dog/5287.png 1 +sketch/dog/5288.png 1 +sketch/dog/5289.png 1 +sketch/dog/5290.png 1 +sketch/dog/5291.png 1 +sketch/dog/5292.png 1 +sketch/dog/5293.png 1 +sketch/dog/5294.png 1 +sketch/dog/5295.png 1 +sketch/dog/5296.png 1 +sketch/dog/5297.png 1 +sketch/dog/5298.png 1 +sketch/dog/5299.png 1 +sketch/dog/5300.png 1 +sketch/dog/5301.png 1 +sketch/dog/5302.png 1 +sketch/dog/5303.png 1 +sketch/dog/5304.png 1 +sketch/dog/5305.png 1 +sketch/dog/5306.png 1 +sketch/dog/5307.png 1 +sketch/dog/5308.png 1 +sketch/dog/5309.png 1 +sketch/dog/5310.png 1 +sketch/dog/5311.png 1 +sketch/dog/5312.png 1 +sketch/dog/5313.png 1 +sketch/dog/5314.png 1 +sketch/dog/5315.png 1 +sketch/dog/5316.png 1 +sketch/dog/5317.png 1 +sketch/dog/5318.png 1 +sketch/dog/5319.png 1 +sketch/dog/5320.png 1 +sketch/dog/5321.png 1 +sketch/dog/5322.png 1 +sketch/dog/5323.png 1 +sketch/dog/5324.png 1 +sketch/dog/5325.png 1 +sketch/dog/5326.png 1 +sketch/dog/5327.png 1 +sketch/dog/5328.png 1 +sketch/dog/5329.png 1 +sketch/dog/5330.png 1 +sketch/dog/5331.png 1 +sketch/dog/5332.png 1 +sketch/dog/5333.png 1 +sketch/dog/5334.png 1 +sketch/dog/5335.png 1 +sketch/dog/5336.png 1 +sketch/dog/5337.png 1 +sketch/dog/5338.png 1 +sketch/dog/5339.png 1 +sketch/dog/5340.png 1 +sketch/dog/5341.png 1 +sketch/dog/5342.png 1 +sketch/dog/5343.png 1 +sketch/dog/5344.png 1 +sketch/dog/5345.png 1 +sketch/dog/5346.png 1 +sketch/dog/5347.png 1 +sketch/dog/5348.png 1 +sketch/dog/5349.png 1 +sketch/dog/5350.png 1 +sketch/dog/5351.png 1 +sketch/dog/5352.png 1 +sketch/dog/5353.png 1 +sketch/dog/5354.png 1 +sketch/dog/5355.png 1 +sketch/dog/5356.png 1 +sketch/dog/5357.png 1 +sketch/dog/5358.png 1 +sketch/dog/5359.png 1 +sketch/dog/5360.png 1 +sketch/elephant/n02503517_1415-1.png 2 +sketch/elephant/n02503517_1415-2.png 2 +sketch/elephant/n02503517_1415-3.png 2 +sketch/elephant/n02503517_1415-4.png 2 +sketch/elephant/n02503517_1415-5.png 2 +sketch/elephant/n02503517_1453-1.png 2 +sketch/elephant/n02503517_1453-2.png 2 +sketch/elephant/n02503517_1453-3.png 2 +sketch/elephant/n02503517_1453-4.png 2 +sketch/elephant/n02503517_1453-5.png 2 +sketch/elephant/n02503517_1453-6.png 2 +sketch/elephant/n02503517_1583-1.png 2 +sketch/elephant/n02503517_1583-2.png 2 +sketch/elephant/n02503517_1583-3.png 2 +sketch/elephant/n02503517_1583-4.png 2 +sketch/elephant/n02503517_1583-5.png 2 +sketch/elephant/n02503517_1583-6.png 2 +sketch/elephant/n02503517_1829-1.png 2 +sketch/elephant/n02503517_1829-2.png 2 +sketch/elephant/n02503517_1829-3.png 2 +sketch/elephant/n02503517_1829-4.png 2 +sketch/elephant/n02503517_1829-5.png 2 +sketch/elephant/n02503517_1852-1.png 2 +sketch/elephant/n02503517_1852-2.png 2 +sketch/elephant/n02503517_1852-3.png 2 +sketch/elephant/n02503517_1852-4.png 2 +sketch/elephant/n02503517_1852-5.png 2 +sketch/elephant/n02503517_1963-1.png 2 +sketch/elephant/n02503517_1963-2.png 2 +sketch/elephant/n02503517_1963-3.png 2 +sketch/elephant/n02503517_1963-4.png 2 +sketch/elephant/n02503517_1963-5.png 2 +sketch/elephant/n02503517_1984-1.png 2 +sketch/elephant/n02503517_1984-2.png 2 +sketch/elephant/n02503517_1984-3.png 2 +sketch/elephant/n02503517_1984-4.png 2 +sketch/elephant/n02503517_1984-5.png 2 +sketch/elephant/n02503517_2061-1.png 2 +sketch/elephant/n02503517_2061-2.png 2 +sketch/elephant/n02503517_2061-3.png 2 +sketch/elephant/n02503517_2061-4.png 2 +sketch/elephant/n02503517_2061-5.png 2 +sketch/elephant/n02503517_2444-1.png 2 +sketch/elephant/n02503517_2444-2.png 2 +sketch/elephant/n02503517_2444-3.png 2 +sketch/elephant/n02503517_2444-4.png 2 +sketch/elephant/n02503517_2444-5.png 2 +sketch/elephant/n02503517_2547-1.png 2 +sketch/elephant/n02503517_2547-2.png 2 +sketch/elephant/n02503517_2547-3.png 2 +sketch/elephant/n02503517_2547-4.png 2 +sketch/elephant/n02503517_2547-5.png 2 +sketch/elephant/n02503517_2547-6.png 2 +sketch/elephant/n02503517_2547-7.png 2 +sketch/elephant/n02503517_2547-8.png 2 +sketch/elephant/n02503517_2547-9.png 2 +sketch/elephant/n02503517_2547-10.png 2 +sketch/elephant/n02503517_2802-1.png 2 +sketch/elephant/n02503517_2802-2.png 2 +sketch/elephant/n02503517_2802-3.png 2 +sketch/elephant/n02503517_2802-4.png 2 +sketch/elephant/n02503517_2802-5.png 2 +sketch/elephant/n02503517_2802-6.png 2 +sketch/elephant/n02503517_2804-1.png 2 +sketch/elephant/n02503517_2804-2.png 2 +sketch/elephant/n02503517_2804-3.png 2 +sketch/elephant/n02503517_2804-4.png 2 +sketch/elephant/n02503517_2804-5.png 2 +sketch/elephant/n02503517_2925-1.png 2 +sketch/elephant/n02503517_2925-2.png 2 +sketch/elephant/n02503517_2925-3.png 2 +sketch/elephant/n02503517_2925-4.png 2 +sketch/elephant/n02503517_2925-5.png 2 +sketch/elephant/n02503517_2925-6.png 2 +sketch/elephant/n02503517_2925-7.png 2 +sketch/elephant/n02503517_2925-8.png 2 +sketch/elephant/n02503517_2925-9.png 2 +sketch/elephant/n02503517_2925-10.png 2 +sketch/elephant/n02503517_2993-1.png 2 +sketch/elephant/n02503517_2993-2.png 2 +sketch/elephant/n02503517_2993-3.png 2 +sketch/elephant/n02503517_2993-4.png 2 +sketch/elephant/n02503517_2993-5.png 2 +sketch/elephant/n02503517_2993-6.png 2 +sketch/elephant/n02503517_2993-7.png 2 +sketch/elephant/n02503517_2993-8.png 2 +sketch/elephant/n02503517_2993-9.png 2 +sketch/elephant/n02503517_2993-10.png 2 +sketch/elephant/n02503517_3037-1.png 2 +sketch/elephant/n02503517_3037-2.png 2 +sketch/elephant/n02503517_3037-3.png 2 +sketch/elephant/n02503517_3037-4.png 2 +sketch/elephant/n02503517_3037-5.png 2 +sketch/elephant/n02503517_3037-6.png 2 +sketch/elephant/n02503517_3037-7.png 2 +sketch/elephant/n02503517_3037-8.png 2 +sketch/elephant/n02503517_3072-1.png 2 +sketch/elephant/n02503517_3072-2.png 2 +sketch/elephant/n02503517_3072-3.png 2 +sketch/elephant/n02503517_3072-4.png 2 +sketch/elephant/n02503517_3072-5.png 2 +sketch/elephant/n02503517_3072-6.png 2 +sketch/elephant/n02503517_3108-1.png 2 +sketch/elephant/n02503517_3108-2.png 2 +sketch/elephant/n02503517_3108-3.png 2 +sketch/elephant/n02503517_3108-4.png 2 +sketch/elephant/n02503517_3108-5.png 2 +sketch/elephant/n02503517_3108-6.png 2 +sketch/elephant/n02503517_3108-7.png 2 +sketch/elephant/n02503517_3108-8.png 2 +sketch/elephant/n02503517_3108-9.png 2 +sketch/elephant/n02503517_3799-1.png 2 +sketch/elephant/n02503517_3799-2.png 2 +sketch/elephant/n02503517_3799-3.png 2 +sketch/elephant/n02503517_3799-4.png 2 +sketch/elephant/n02503517_3799-5.png 2 +sketch/elephant/n02503517_3803-1.png 2 +sketch/elephant/n02503517_3803-2.png 2 +sketch/elephant/n02503517_3803-3.png 2 +sketch/elephant/n02503517_3803-4.png 2 +sketch/elephant/n02503517_3803-5.png 2 +sketch/elephant/n02503517_3803-6.png 2 +sketch/elephant/n02503517_3808-1.png 2 +sketch/elephant/n02503517_3808-2.png 2 +sketch/elephant/n02503517_3808-3.png 2 +sketch/elephant/n02503517_3808-4.png 2 +sketch/elephant/n02503517_3808-5.png 2 +sketch/elephant/n02503517_3808-6.png 2 +sketch/elephant/n02503517_3808-7.png 2 +sketch/elephant/n02503517_3808-8.png 2 +sketch/elephant/n02503517_3808-9.png 2 +sketch/elephant/n02503517_3808-10.png 2 +sketch/elephant/n02503517_3879-1.png 2 +sketch/elephant/n02503517_3879-2.png 2 +sketch/elephant/n02503517_3879-3.png 2 +sketch/elephant/n02503517_3879-4.png 2 +sketch/elephant/n02503517_3879-5.png 2 +sketch/elephant/n02503517_3879-6.png 2 +sketch/elephant/n02503517_3879-7.png 2 +sketch/elephant/n02503517_4221-1.png 2 +sketch/elephant/n02503517_4221-2.png 2 +sketch/elephant/n02503517_4221-3.png 2 +sketch/elephant/n02503517_4221-4.png 2 +sketch/elephant/n02503517_4221-5.png 2 +sketch/elephant/n02503517_4221-6.png 2 +sketch/elephant/n02503517_4221-7.png 2 +sketch/elephant/n02503517_4247-1.png 2 +sketch/elephant/n02503517_4247-2.png 2 +sketch/elephant/n02503517_4247-3.png 2 +sketch/elephant/n02503517_4247-4.png 2 +sketch/elephant/n02503517_4247-5.png 2 +sketch/elephant/n02503517_4247-6.png 2 +sketch/elephant/n02503517_4247-7.png 2 +sketch/elephant/n02503517_4247-8.png 2 +sketch/elephant/n02503517_4247-9.png 2 +sketch/elephant/n02503517_4247-10.png 2 +sketch/elephant/n02503517_4253-1.png 2 +sketch/elephant/n02503517_4253-2.png 2 +sketch/elephant/n02503517_4253-3.png 2 +sketch/elephant/n02503517_4253-4.png 2 +sketch/elephant/n02503517_4253-5.png 2 +sketch/elephant/n02503517_4413-1.png 2 +sketch/elephant/n02503517_4413-2.png 2 +sketch/elephant/n02503517_4413-3.png 2 +sketch/elephant/n02503517_4413-4.png 2 +sketch/elephant/n02503517_4413-5.png 2 +sketch/elephant/n02503517_4413-6.png 2 +sketch/elephant/n02503517_4413-7.png 2 +sketch/elephant/n02503517_4413-8.png 2 +sketch/elephant/n02503517_4413-9.png 2 +sketch/elephant/n02503517_4413-10.png 2 +sketch/elephant/n02503517_4605-1.png 2 +sketch/elephant/n02503517_4605-2.png 2 +sketch/elephant/n02503517_4605-3.png 2 +sketch/elephant/n02503517_4605-4.png 2 +sketch/elephant/n02503517_4605-5.png 2 +sketch/elephant/n02503517_4687-1.png 2 +sketch/elephant/n02503517_4687-2.png 2 +sketch/elephant/n02503517_4687-3.png 2 +sketch/elephant/n02503517_4687-4.png 2 +sketch/elephant/n02503517_4687-5.png 2 +sketch/elephant/n02503517_4687-6.png 2 +sketch/elephant/n02503517_5117-1.png 2 +sketch/elephant/n02503517_5117-2.png 2 +sketch/elephant/n02503517_5117-3.png 2 +sketch/elephant/n02503517_5117-4.png 2 +sketch/elephant/n02503517_5117-5.png 2 +sketch/elephant/n02503517_5117-6.png 2 +sketch/elephant/n02503517_5267-1.png 2 +sketch/elephant/n02503517_5267-2.png 2 +sketch/elephant/n02503517_5267-3.png 2 +sketch/elephant/n02503517_5267-4.png 2 +sketch/elephant/n02503517_5267-5.png 2 +sketch/elephant/n02503517_5267-6.png 2 +sketch/elephant/n02503517_5267-7.png 2 +sketch/elephant/n02503517_5287-1.png 2 +sketch/elephant/n02503517_5287-2.png 2 +sketch/elephant/n02503517_5287-3.png 2 +sketch/elephant/n02503517_5287-4.png 2 +sketch/elephant/n02503517_5287-5.png 2 +sketch/elephant/n02503517_5418-1.png 2 +sketch/elephant/n02503517_5418-2.png 2 +sketch/elephant/n02503517_5418-3.png 2 +sketch/elephant/n02503517_5418-4.png 2 +sketch/elephant/n02503517_5418-5.png 2 +sketch/elephant/n02503517_5418-6.png 2 +sketch/elephant/n02503517_5418-7.png 2 +sketch/elephant/n02503517_5418-8.png 2 +sketch/elephant/n02503517_5418-9.png 2 +sketch/elephant/n02503517_5418-10.png 2 +sketch/elephant/n02503517_5420-1.png 2 +sketch/elephant/n02503517_5420-2.png 2 +sketch/elephant/n02503517_5420-3.png 2 +sketch/elephant/n02503517_5420-4.png 2 +sketch/elephant/n02503517_5420-5.png 2 +sketch/elephant/n02503517_5420-6.png 2 +sketch/elephant/n02503517_5420-7.png 2 +sketch/elephant/n02503517_5527-1.png 2 +sketch/elephant/n02503517_5527-2.png 2 +sketch/elephant/n02503517_5527-3.png 2 +sketch/elephant/n02503517_5527-4.png 2 +sketch/elephant/n02503517_5527-5.png 2 +sketch/elephant/n02503517_5527-6.png 2 +sketch/elephant/n02503517_5892-1.png 2 +sketch/elephant/n02503517_5892-2.png 2 +sketch/elephant/n02503517_5892-3.png 2 +sketch/elephant/n02503517_5892-4.png 2 +sketch/elephant/n02503517_5892-5.png 2 +sketch/elephant/n02503517_5892-6.png 2 +sketch/elephant/n02503517_5892-7.png 2 +sketch/elephant/n02503517_5905-2.png 2 +sketch/elephant/n02503517_5905-3.png 2 +sketch/elephant/n02503517_5905-4.png 2 +sketch/elephant/n02503517_5905-5.png 2 +sketch/elephant/n02503517_5905-6.png 2 +sketch/elephant/n02503517_5905-7.png 2 +sketch/elephant/n02503517_5905-8.png 2 +sketch/elephant/n02503517_5905-9.png 2 +sketch/elephant/n02503517_5905-10.png 2 +sketch/elephant/n02503517_5905-11.png 2 +sketch/elephant/n02503517_5909-1.png 2 +sketch/elephant/n02503517_5909-2.png 2 +sketch/elephant/n02503517_5909-3.png 2 +sketch/elephant/n02503517_5909-4.png 2 +sketch/elephant/n02503517_5909-5.png 2 +sketch/elephant/n02503517_6032-1.png 2 +sketch/elephant/n02503517_6032-2.png 2 +sketch/elephant/n02503517_6032-3.png 2 +sketch/elephant/n02503517_6032-4.png 2 +sketch/elephant/n02503517_6032-5.png 2 +sketch/elephant/n02503517_6032-6.png 2 +sketch/elephant/n02503517_6043-1.png 2 +sketch/elephant/n02503517_6043-2.png 2 +sketch/elephant/n02503517_6043-3.png 2 +sketch/elephant/n02503517_6043-4.png 2 +sketch/elephant/n02503517_6043-5.png 2 +sketch/elephant/n02503517_6043-6.png 2 +sketch/elephant/n02503517_6232-1.png 2 +sketch/elephant/n02503517_6232-2.png 2 +sketch/elephant/n02503517_6232-3.png 2 +sketch/elephant/n02503517_6232-4.png 2 +sketch/elephant/n02503517_6232-5.png 2 +sketch/elephant/n02503517_6232-6.png 2 +sketch/elephant/n02503517_6232-7.png 2 +sketch/elephant/n02503517_6396-1.png 2 +sketch/elephant/n02503517_6396-2.png 2 +sketch/elephant/n02503517_6396-3.png 2 +sketch/elephant/n02503517_6396-4.png 2 +sketch/elephant/n02503517_6396-5.png 2 +sketch/elephant/n02503517_6429-1.png 2 +sketch/elephant/n02503517_6429-2.png 2 +sketch/elephant/n02503517_6429-3.png 2 +sketch/elephant/n02503517_6429-4.png 2 +sketch/elephant/n02503517_6429-5.png 2 +sketch/elephant/n02503517_6479-1.png 2 +sketch/elephant/n02503517_6479-2.png 2 +sketch/elephant/n02503517_6479-3.png 2 +sketch/elephant/n02503517_6479-4.png 2 +sketch/elephant/n02503517_6479-5.png 2 +sketch/elephant/n02503517_6479-6.png 2 +sketch/elephant/n02503517_6479-7.png 2 +sketch/elephant/n02503517_6479-8.png 2 +sketch/elephant/n02503517_6511-1.png 2 +sketch/elephant/n02503517_6511-2.png 2 +sketch/elephant/n02503517_6511-3.png 2 +sketch/elephant/n02503517_6511-4.png 2 +sketch/elephant/n02503517_6511-5.png 2 +sketch/elephant/n02503517_6611-1.png 2 +sketch/elephant/n02503517_6611-2.png 2 +sketch/elephant/n02503517_6611-3.png 2 +sketch/elephant/n02503517_6611-4.png 2 +sketch/elephant/n02503517_6611-5.png 2 +sketch/elephant/n02503517_6611-6.png 2 +sketch/elephant/n02503517_6611-7.png 2 +sketch/elephant/n02503517_6611-8.png 2 +sketch/elephant/n02503517_6611-9.png 2 +sketch/elephant/n02503517_6611-10.png 2 +sketch/elephant/n02503517_6613-1.png 2 +sketch/elephant/n02503517_6613-2.png 2 +sketch/elephant/n02503517_6613-3.png 2 +sketch/elephant/n02503517_6613-4.png 2 +sketch/elephant/n02503517_6613-5.png 2 +sketch/elephant/n02503517_6624-1.png 2 +sketch/elephant/n02503517_6624-2.png 2 +sketch/elephant/n02503517_6624-3.png 2 +sketch/elephant/n02503517_6624-4.png 2 +sketch/elephant/n02503517_6624-5.png 2 +sketch/elephant/n02503517_6624-6.png 2 +sketch/elephant/n02503517_6661-1.png 2 +sketch/elephant/n02503517_6661-2.png 2 +sketch/elephant/n02503517_6661-3.png 2 +sketch/elephant/n02503517_6661-4.png 2 +sketch/elephant/n02503517_6661-5.png 2 +sketch/elephant/n02503517_6784-1.png 2 +sketch/elephant/n02503517_6784-2.png 2 +sketch/elephant/n02503517_6784-3.png 2 +sketch/elephant/n02503517_6784-4.png 2 +sketch/elephant/n02503517_6784-5.png 2 +sketch/elephant/n02503517_6880-1.png 2 +sketch/elephant/n02503517_6880-2.png 2 +sketch/elephant/n02503517_6880-3.png 2 +sketch/elephant/n02503517_6880-4.png 2 +sketch/elephant/n02503517_6880-5.png 2 +sketch/elephant/n02503517_6937-1.png 2 +sketch/elephant/n02503517_6937-2.png 2 +sketch/elephant/n02503517_6937-3.png 2 +sketch/elephant/n02503517_6937-4.png 2 +sketch/elephant/n02503517_6937-5.png 2 +sketch/elephant/n02503517_6937-6.png 2 +sketch/elephant/n02503517_7020-1.png 2 +sketch/elephant/n02503517_7020-2.png 2 +sketch/elephant/n02503517_7020-3.png 2 +sketch/elephant/n02503517_7020-4.png 2 +sketch/elephant/n02503517_7020-5.png 2 +sketch/elephant/n02503517_7020-6.png 2 +sketch/elephant/n02503517_7031-1.png 2 +sketch/elephant/n02503517_7031-2.png 2 +sketch/elephant/n02503517_7031-3.png 2 +sketch/elephant/n02503517_7031-4.png 2 +sketch/elephant/n02503517_7031-5.png 2 +sketch/elephant/n02503517_7031-6.png 2 +sketch/elephant/n02503517_7031-7.png 2 +sketch/elephant/n02503517_7031-8.png 2 +sketch/elephant/n02503517_7031-9.png 2 +sketch/elephant/n02503517_7031-10.png 2 +sketch/elephant/n02503517_7083-1.png 2 +sketch/elephant/n02503517_7083-2.png 2 +sketch/elephant/n02503517_7083-3.png 2 +sketch/elephant/n02503517_7083-4.png 2 +sketch/elephant/n02503517_7083-5.png 2 +sketch/elephant/n02503517_7173-1.png 2 +sketch/elephant/n02503517_7173-2.png 2 +sketch/elephant/n02503517_7173-3.png 2 +sketch/elephant/n02503517_7173-4.png 2 +sketch/elephant/n02503517_7173-5.png 2 +sketch/elephant/n02503517_7211-1.png 2 +sketch/elephant/n02503517_7211-2.png 2 +sketch/elephant/n02503517_7211-3.png 2 +sketch/elephant/n02503517_7211-4.png 2 +sketch/elephant/n02503517_7211-5.png 2 +sketch/elephant/n02503517_7393-1.png 2 +sketch/elephant/n02503517_7393-2.png 2 +sketch/elephant/n02503517_7393-3.png 2 +sketch/elephant/n02503517_7393-4.png 2 +sketch/elephant/n02503517_7393-5.png 2 +sketch/elephant/n02503517_7393-6.png 2 +sketch/elephant/n02503517_7393-7.png 2 +sketch/elephant/n02503517_7592-1.png 2 +sketch/elephant/n02503517_7592-2.png 2 +sketch/elephant/n02503517_7592-3.png 2 +sketch/elephant/n02503517_7592-4.png 2 +sketch/elephant/n02503517_7592-5.png 2 +sketch/elephant/n02503517_7592-6.png 2 +sketch/elephant/n02503517_7592-7.png 2 +sketch/elephant/n02503517_7592-8.png 2 +sketch/elephant/n02503517_8137-1.png 2 +sketch/elephant/n02503517_8137-2.png 2 +sketch/elephant/n02503517_8137-3.png 2 +sketch/elephant/n02503517_8137-4.png 2 +sketch/elephant/n02503517_8137-5.png 2 +sketch/elephant/n02503517_8205-1.png 2 +sketch/elephant/n02503517_8205-2.png 2 +sketch/elephant/n02503517_8205-3.png 2 +sketch/elephant/n02503517_8205-4.png 2 +sketch/elephant/n02503517_8205-5.png 2 +sketch/elephant/n02503517_8222-1.png 2 +sketch/elephant/n02503517_8222-2.png 2 +sketch/elephant/n02503517_8222-3.png 2 +sketch/elephant/n02503517_8222-4.png 2 +sketch/elephant/n02503517_8222-5.png 2 +sketch/elephant/n02503517_8265-1.png 2 +sketch/elephant/n02503517_8265-2.png 2 +sketch/elephant/n02503517_8265-3.png 2 +sketch/elephant/n02503517_8265-4.png 2 +sketch/elephant/n02503517_8265-5.png 2 +sketch/elephant/n02503517_8292-1.png 2 +sketch/elephant/n02503517_8292-2.png 2 +sketch/elephant/n02503517_8292-3.png 2 +sketch/elephant/n02503517_8292-4.png 2 +sketch/elephant/n02503517_8292-5.png 2 +sketch/elephant/n02503517_8292-6.png 2 +sketch/elephant/n02503517_8518-1.png 2 +sketch/elephant/n02503517_8518-2.png 2 +sketch/elephant/n02503517_8518-3.png 2 +sketch/elephant/n02503517_8518-4.png 2 +sketch/elephant/n02503517_8518-5.png 2 +sketch/elephant/n02503517_8518-6.png 2 +sketch/elephant/n02503517_8571-1.png 2 +sketch/elephant/n02503517_8571-2.png 2 +sketch/elephant/n02503517_8571-3.png 2 +sketch/elephant/n02503517_8571-4.png 2 +sketch/elephant/n02503517_8571-5.png 2 +sketch/elephant/n02503517_8571-6.png 2 +sketch/elephant/n02503517_8757-1.png 2 +sketch/elephant/n02503517_8757-2.png 2 +sketch/elephant/n02503517_8757-3.png 2 +sketch/elephant/n02503517_8757-4.png 2 +sketch/elephant/n02503517_8757-5.png 2 +sketch/elephant/n02503517_8757-6.png 2 +sketch/elephant/n02503517_8901-1.png 2 +sketch/elephant/n02503517_8901-2.png 2 +sketch/elephant/n02503517_8901-3.png 2 +sketch/elephant/n02503517_8901-4.png 2 +sketch/elephant/n02503517_8901-5.png 2 +sketch/elephant/n02503517_8901-6.png 2 +sketch/elephant/n02503517_8901-7.png 2 +sketch/elephant/n02503517_8904-1.png 2 +sketch/elephant/n02503517_8904-2.png 2 +sketch/elephant/n02503517_8904-3.png 2 +sketch/elephant/n02503517_8904-4.png 2 +sketch/elephant/n02503517_8904-5.png 2 +sketch/elephant/n02503517_8904-6.png 2 +sketch/elephant/n02503517_8938-1.png 2 +sketch/elephant/n02503517_8938-2.png 2 +sketch/elephant/n02503517_8938-3.png 2 +sketch/elephant/n02503517_8938-4.png 2 +sketch/elephant/n02503517_8938-5.png 2 +sketch/elephant/n02503517_8938-6.png 2 +sketch/elephant/n02503517_9043-1.png 2 +sketch/elephant/n02503517_9043-2.png 2 +sketch/elephant/n02503517_9043-3.png 2 +sketch/elephant/n02503517_9043-4.png 2 +sketch/elephant/n02503517_9043-5.png 2 +sketch/elephant/n02503517_9043-6.png 2 +sketch/elephant/n02503517_9043-7.png 2 +sketch/elephant/n02503517_9043-8.png 2 +sketch/elephant/n02503517_9043-9.png 2 +sketch/elephant/n02503517_9043-10.png 2 +sketch/elephant/n02503517_9154-1.png 2 +sketch/elephant/n02503517_9154-2.png 2 +sketch/elephant/n02503517_9154-3.png 2 +sketch/elephant/n02503517_9154-4.png 2 +sketch/elephant/n02503517_9154-5.png 2 +sketch/elephant/n02503517_9154-6.png 2 +sketch/elephant/n02503517_9237-1.png 2 +sketch/elephant/n02503517_9237-2.png 2 +sketch/elephant/n02503517_9237-3.png 2 +sketch/elephant/n02503517_9237-4.png 2 +sketch/elephant/n02503517_9237-5.png 2 +sketch/elephant/n02503517_9237-6.png 2 +sketch/elephant/n02503517_9237-7.png 2 +sketch/elephant/n02503517_9241-1.png 2 +sketch/elephant/n02503517_9241-2.png 2 +sketch/elephant/n02503517_9241-3.png 2 +sketch/elephant/n02503517_9241-4.png 2 +sketch/elephant/n02503517_9241-5.png 2 +sketch/elephant/n02503517_9270-1.png 2 +sketch/elephant/n02503517_9270-2.png 2 +sketch/elephant/n02503517_9270-3.png 2 +sketch/elephant/n02503517_9270-4.png 2 +sketch/elephant/n02503517_9270-5.png 2 +sketch/elephant/n02503517_9270-6.png 2 +sketch/elephant/n02503517_9270-7.png 2 +sketch/elephant/n02503517_9270-8.png 2 +sketch/elephant/n02503517_9270-9.png 2 +sketch/elephant/n02503517_9270-10.png 2 +sketch/elephant/n02503517_9421-1.png 2 +sketch/elephant/n02503517_9421-2.png 2 +sketch/elephant/n02503517_9421-3.png 2 +sketch/elephant/n02503517_9421-4.png 2 +sketch/elephant/n02503517_9421-5.png 2 +sketch/elephant/n02503517_9421-6.png 2 +sketch/elephant/n02503517_9421-7.png 2 +sketch/elephant/n02503517_9421-8.png 2 +sketch/elephant/n02503517_9421-9.png 2 +sketch/elephant/n02503517_9827-1.png 2 +sketch/elephant/n02503517_9827-2.png 2 +sketch/elephant/n02503517_9827-3.png 2 +sketch/elephant/n02503517_9827-4.png 2 +sketch/elephant/n02503517_9827-5.png 2 +sketch/elephant/n02503517_9827-6.png 2 +sketch/elephant/n02503517_9827-7.png 2 +sketch/elephant/n02503517_9827-8.png 2 +sketch/elephant/n02503517_10036-1.png 2 +sketch/elephant/n02503517_10036-2.png 2 +sketch/elephant/n02503517_10036-3.png 2 +sketch/elephant/n02503517_10036-4.png 2 +sketch/elephant/n02503517_10036-5.png 2 +sketch/elephant/n02503517_10036-6.png 2 +sketch/elephant/n02503517_10036-7.png 2 +sketch/elephant/n02503517_10036-8.png 2 +sketch/elephant/n02503517_10036-9.png 2 +sketch/elephant/n02503517_10036-10.png 2 +sketch/elephant/n02503517_10075-1.png 2 +sketch/elephant/n02503517_10075-2.png 2 +sketch/elephant/n02503517_10075-3.png 2 +sketch/elephant/n02503517_10075-4.png 2 +sketch/elephant/n02503517_10075-5.png 2 +sketch/elephant/n02503517_10193-1.png 2 +sketch/elephant/n02503517_10193-2.png 2 +sketch/elephant/n02503517_10193-3.png 2 +sketch/elephant/n02503517_10193-4.png 2 +sketch/elephant/n02503517_10193-5.png 2 +sketch/elephant/n02503517_10193-6.png 2 +sketch/elephant/n02503517_10193-7.png 2 +sketch/elephant/n02503517_10193-8.png 2 +sketch/elephant/n02503517_10193-9.png 2 +sketch/elephant/n02503517_10193-10.png 2 +sketch/elephant/n02503517_10259-1.png 2 +sketch/elephant/n02503517_10259-2.png 2 +sketch/elephant/n02503517_10259-3.png 2 +sketch/elephant/n02503517_10259-4.png 2 +sketch/elephant/n02503517_10259-5.png 2 +sketch/elephant/n02503517_10259-6.png 2 +sketch/elephant/n02503517_10259-7.png 2 +sketch/elephant/n02503517_10259-8.png 2 +sketch/elephant/n02503517_10259-9.png 2 +sketch/elephant/n02503517_10275-1.png 2 +sketch/elephant/n02503517_10275-2.png 2 +sketch/elephant/n02503517_10275-3.png 2 +sketch/elephant/n02503517_10275-4.png 2 +sketch/elephant/n02503517_10275-5.png 2 +sketch/elephant/n02503517_10275-6.png 2 +sketch/elephant/n02503517_10300-1.png 2 +sketch/elephant/n02503517_10300-2.png 2 +sketch/elephant/n02503517_10300-3.png 2 +sketch/elephant/n02503517_10300-4.png 2 +sketch/elephant/n02503517_10300-5.png 2 +sketch/elephant/n02503517_10439-1.png 2 +sketch/elephant/n02503517_10439-2.png 2 +sketch/elephant/n02503517_10439-3.png 2 +sketch/elephant/n02503517_10439-4.png 2 +sketch/elephant/n02503517_10439-5.png 2 +sketch/elephant/n02503517_10439-6.png 2 +sketch/elephant/n02503517_10439-7.png 2 +sketch/elephant/n02503517_10439-8.png 2 +sketch/elephant/n02503517_10440-1.png 2 +sketch/elephant/n02503517_10440-2.png 2 +sketch/elephant/n02503517_10440-3.png 2 +sketch/elephant/n02503517_10440-4.png 2 +sketch/elephant/n02503517_10440-5.png 2 +sketch/elephant/n02503517_10440-6.png 2 +sketch/elephant/n02503517_10440-7.png 2 +sketch/elephant/n02503517_10440-8.png 2 +sketch/elephant/n02503517_10440-9.png 2 +sketch/elephant/n02503517_10528-1.png 2 +sketch/elephant/n02503517_10528-2.png 2 +sketch/elephant/n02503517_10528-3.png 2 +sketch/elephant/n02503517_10528-4.png 2 +sketch/elephant/n02503517_10528-5.png 2 +sketch/elephant/n02503517_10558-1.png 2 +sketch/elephant/n02503517_10558-2.png 2 +sketch/elephant/n02503517_10558-3.png 2 +sketch/elephant/n02503517_10558-4.png 2 +sketch/elephant/n02503517_10558-5.png 2 +sketch/elephant/n02503517_10778-1.png 2 +sketch/elephant/n02503517_10778-2.png 2 +sketch/elephant/n02503517_10778-3.png 2 +sketch/elephant/n02503517_10778-4.png 2 +sketch/elephant/n02503517_10778-5.png 2 +sketch/elephant/n02503517_10778-6.png 2 +sketch/elephant/n02503517_11873-1.png 2 +sketch/elephant/n02503517_11873-2.png 2 +sketch/elephant/n02503517_11873-3.png 2 +sketch/elephant/n02503517_11873-4.png 2 +sketch/elephant/n02503517_11873-5.png 2 +sketch/elephant/n02503517_11873-6.png 2 +sketch/elephant/n02503517_11873-7.png 2 +sketch/elephant/n02503517_11873-8.png 2 +sketch/elephant/n02503517_11873-9.png 2 +sketch/elephant/n02503517_12688-1.png 2 +sketch/elephant/n02503517_12688-2.png 2 +sketch/elephant/n02503517_12688-3.png 2 +sketch/elephant/n02503517_12688-4.png 2 +sketch/elephant/n02503517_12688-5.png 2 +sketch/elephant/5921.png 2 +sketch/elephant/5922.png 2 +sketch/elephant/5923.png 2 +sketch/elephant/5924.png 2 +sketch/elephant/5925.png 2 +sketch/elephant/5926.png 2 +sketch/elephant/5927.png 2 +sketch/elephant/5928.png 2 +sketch/elephant/5929.png 2 +sketch/elephant/5930.png 2 +sketch/elephant/5931.png 2 +sketch/elephant/5932.png 2 +sketch/elephant/5933.png 2 +sketch/elephant/5934.png 2 +sketch/elephant/5935.png 2 +sketch/elephant/5936.png 2 +sketch/elephant/5937.png 2 +sketch/elephant/5938.png 2 +sketch/elephant/5939.png 2 +sketch/elephant/5940.png 2 +sketch/elephant/5941.png 2 +sketch/elephant/5942.png 2 +sketch/elephant/5943.png 2 +sketch/elephant/5944.png 2 +sketch/elephant/5945.png 2 +sketch/elephant/5946.png 2 +sketch/elephant/5947.png 2 +sketch/elephant/5948.png 2 +sketch/elephant/5949.png 2 +sketch/elephant/5950.png 2 +sketch/elephant/5951.png 2 +sketch/elephant/5952.png 2 +sketch/elephant/5953.png 2 +sketch/elephant/5954.png 2 +sketch/elephant/5955.png 2 +sketch/elephant/5956.png 2 +sketch/elephant/5957.png 2 +sketch/elephant/5958.png 2 +sketch/elephant/5959.png 2 +sketch/elephant/5960.png 2 +sketch/elephant/5961.png 2 +sketch/elephant/5962.png 2 +sketch/elephant/5963.png 2 +sketch/elephant/5964.png 2 +sketch/elephant/5965.png 2 +sketch/elephant/5966.png 2 +sketch/elephant/5967.png 2 +sketch/elephant/5968.png 2 +sketch/elephant/5969.png 2 +sketch/elephant/5970.png 2 +sketch/elephant/5971.png 2 +sketch/elephant/5972.png 2 +sketch/elephant/5973.png 2 +sketch/elephant/5974.png 2 +sketch/elephant/5975.png 2 +sketch/elephant/5976.png 2 +sketch/elephant/5977.png 2 +sketch/elephant/5978.png 2 +sketch/elephant/5979.png 2 +sketch/elephant/5980.png 2 +sketch/elephant/5981.png 2 +sketch/elephant/5982.png 2 +sketch/elephant/5983.png 2 +sketch/elephant/5984.png 2 +sketch/elephant/5985.png 2 +sketch/elephant/5986.png 2 +sketch/elephant/5987.png 2 +sketch/elephant/5988.png 2 +sketch/elephant/5989.png 2 +sketch/elephant/5990.png 2 +sketch/elephant/5991.png 2 +sketch/elephant/5992.png 2 +sketch/elephant/5993.png 2 +sketch/elephant/5994.png 2 +sketch/elephant/5995.png 2 +sketch/elephant/5996.png 2 +sketch/elephant/5997.png 2 +sketch/elephant/5998.png 2 +sketch/elephant/5999.png 2 +sketch/elephant/6000.png 2 +sketch/giraffe/n02439033_2677-3.png 3 +sketch/giraffe/n02439033_2677-4.png 3 +sketch/giraffe/n02439033_2677-5.png 3 +sketch/giraffe/n02439033_2677-6.png 3 +sketch/giraffe/n02439033_2677-7.png 3 +sketch/giraffe/n02439033_3944-1.png 3 +sketch/giraffe/n02439033_3944-2.png 3 +sketch/giraffe/n02439033_3944-3.png 3 +sketch/giraffe/n02439033_3944-4.png 3 +sketch/giraffe/n02439033_3944-5.png 3 +sketch/giraffe/n02439033_3944-6.png 3 +sketch/giraffe/n02439033_3944-7.png 3 +sketch/giraffe/n02439033_3944-8.png 3 +sketch/giraffe/n02439033_3944-9.png 3 +sketch/giraffe/n02439033_3944-10.png 3 +sketch/giraffe/n02439033_4601-1.png 3 +sketch/giraffe/n02439033_4601-2.png 3 +sketch/giraffe/n02439033_4601-3.png 3 +sketch/giraffe/n02439033_4601-4.png 3 +sketch/giraffe/n02439033_4601-5.png 3 +sketch/giraffe/n02439033_5004-1.png 3 +sketch/giraffe/n02439033_5004-2.png 3 +sketch/giraffe/n02439033_5004-3.png 3 +sketch/giraffe/n02439033_5004-4.png 3 +sketch/giraffe/n02439033_5004-5.png 3 +sketch/giraffe/n02439033_5004-6.png 3 +sketch/giraffe/n02439033_5004-7.png 3 +sketch/giraffe/n02439033_5004-8.png 3 +sketch/giraffe/n02439033_5652-1.png 3 +sketch/giraffe/n02439033_5652-2.png 3 +sketch/giraffe/n02439033_5652-3.png 3 +sketch/giraffe/n02439033_5652-4.png 3 +sketch/giraffe/n02439033_5652-5.png 3 +sketch/giraffe/n02439033_6552-1.png 3 +sketch/giraffe/n02439033_6552-2.png 3 +sketch/giraffe/n02439033_6552-3.png 3 +sketch/giraffe/n02439033_6552-4.png 3 +sketch/giraffe/n02439033_6552-5.png 3 +sketch/giraffe/n02439033_8789-1.png 3 +sketch/giraffe/n02439033_8789-2.png 3 +sketch/giraffe/n02439033_8789-3.png 3 +sketch/giraffe/n02439033_8789-4.png 3 +sketch/giraffe/n02439033_8789-5.png 3 +sketch/giraffe/n02439033_8846-1.png 3 +sketch/giraffe/n02439033_8846-2.png 3 +sketch/giraffe/n02439033_8846-3.png 3 +sketch/giraffe/n02439033_8846-4.png 3 +sketch/giraffe/n02439033_8846-5.png 3 +sketch/giraffe/n02439033_8846-6.png 3 +sketch/giraffe/n02439033_8846-7.png 3 +sketch/giraffe/n02439033_8846-8.png 3 +sketch/giraffe/n02439033_8846-9.png 3 +sketch/giraffe/n02439033_8846-10.png 3 +sketch/giraffe/n02439033_8846-11.png 3 +sketch/giraffe/n02439033_8846-12.png 3 +sketch/giraffe/n02439033_8846-13.png 3 +sketch/giraffe/n02439033_8875-1.png 3 +sketch/giraffe/n02439033_8875-2.png 3 +sketch/giraffe/n02439033_8875-3.png 3 +sketch/giraffe/n02439033_8875-4.png 3 +sketch/giraffe/n02439033_8875-5.png 3 +sketch/giraffe/n02439033_8875-6.png 3 +sketch/giraffe/n02439033_8875-7.png 3 +sketch/giraffe/n02439033_8875-8.png 3 +sketch/giraffe/n02439033_9257-1.png 3 +sketch/giraffe/n02439033_9257-2.png 3 +sketch/giraffe/n02439033_9257-3.png 3 +sketch/giraffe/n02439033_9257-4.png 3 +sketch/giraffe/n02439033_9257-5.png 3 +sketch/giraffe/n02439033_9257-6.png 3 +sketch/giraffe/n02439033_9261-1.png 3 +sketch/giraffe/n02439033_9261-2.png 3 +sketch/giraffe/n02439033_9261-3.png 3 +sketch/giraffe/n02439033_9261-4.png 3 +sketch/giraffe/n02439033_9261-5.png 3 +sketch/giraffe/n02439033_9398-1.png 3 +sketch/giraffe/n02439033_9398-2.png 3 +sketch/giraffe/n02439033_9398-3.png 3 +sketch/giraffe/n02439033_9398-4.png 3 +sketch/giraffe/n02439033_9398-5.png 3 +sketch/giraffe/n02439033_9398-6.png 3 +sketch/giraffe/n02439033_9472-1.png 3 +sketch/giraffe/n02439033_9472-2.png 3 +sketch/giraffe/n02439033_9472-3.png 3 +sketch/giraffe/n02439033_9472-4.png 3 +sketch/giraffe/n02439033_9472-5.png 3 +sketch/giraffe/n02439033_9472-6.png 3 +sketch/giraffe/n02439033_9472-7.png 3 +sketch/giraffe/n02439033_9472-8.png 3 +sketch/giraffe/n02439033_9472-9.png 3 +sketch/giraffe/n02439033_9472-10.png 3 +sketch/giraffe/n02439033_9598-1.png 3 +sketch/giraffe/n02439033_9598-2.png 3 +sketch/giraffe/n02439033_9598-3.png 3 +sketch/giraffe/n02439033_9598-4.png 3 +sketch/giraffe/n02439033_9598-5.png 3 +sketch/giraffe/n02439033_9598-6.png 3 +sketch/giraffe/n02439033_9598-7.png 3 +sketch/giraffe/n02439033_9598-8.png 3 +sketch/giraffe/n02439033_9598-9.png 3 +sketch/giraffe/n02439033_9598-10.png 3 +sketch/giraffe/n02439033_9604-1.png 3 +sketch/giraffe/n02439033_9604-2.png 3 +sketch/giraffe/n02439033_9604-3.png 3 +sketch/giraffe/n02439033_9604-4.png 3 +sketch/giraffe/n02439033_9604-5.png 3 +sketch/giraffe/n02439033_9679-1.png 3 +sketch/giraffe/n02439033_9679-2.png 3 +sketch/giraffe/n02439033_9679-3.png 3 +sketch/giraffe/n02439033_9679-4.png 3 +sketch/giraffe/n02439033_9679-5.png 3 +sketch/giraffe/n02439033_9719-1.png 3 +sketch/giraffe/n02439033_9719-2.png 3 +sketch/giraffe/n02439033_9719-3.png 3 +sketch/giraffe/n02439033_9719-4.png 3 +sketch/giraffe/n02439033_9719-5.png 3 +sketch/giraffe/n02439033_9719-6.png 3 +sketch/giraffe/n02439033_9719-7.png 3 +sketch/giraffe/n02439033_9719-8.png 3 +sketch/giraffe/n02439033_9719-9.png 3 +sketch/giraffe/n02439033_10130-1.png 3 +sketch/giraffe/n02439033_10130-2.png 3 +sketch/giraffe/n02439033_10130-3.png 3 +sketch/giraffe/n02439033_10130-4.png 3 +sketch/giraffe/n02439033_10130-5.png 3 +sketch/giraffe/n02439033_10130-6.png 3 +sketch/giraffe/n02439033_10130-7.png 3 +sketch/giraffe/n02439033_10164-1.png 3 +sketch/giraffe/n02439033_10164-2.png 3 +sketch/giraffe/n02439033_10164-3.png 3 +sketch/giraffe/n02439033_10164-4.png 3 +sketch/giraffe/n02439033_10164-5.png 3 +sketch/giraffe/n02439033_10164-6.png 3 +sketch/giraffe/n02439033_10164-7.png 3 +sketch/giraffe/n02439033_10164-8.png 3 +sketch/giraffe/n02439033_10164-9.png 3 +sketch/giraffe/n02439033_10164-10.png 3 +sketch/giraffe/n02439033_10279-1.png 3 +sketch/giraffe/n02439033_10279-2.png 3 +sketch/giraffe/n02439033_10279-3.png 3 +sketch/giraffe/n02439033_10279-4.png 3 +sketch/giraffe/n02439033_10279-5.png 3 +sketch/giraffe/n02439033_10279-6.png 3 +sketch/giraffe/n02439033_10295-1.png 3 +sketch/giraffe/n02439033_10295-2.png 3 +sketch/giraffe/n02439033_10295-3.png 3 +sketch/giraffe/n02439033_10295-4.png 3 +sketch/giraffe/n02439033_10295-5.png 3 +sketch/giraffe/n02439033_10453-1.png 3 +sketch/giraffe/n02439033_10453-2.png 3 +sketch/giraffe/n02439033_10453-3.png 3 +sketch/giraffe/n02439033_10453-4.png 3 +sketch/giraffe/n02439033_10453-5.png 3 +sketch/giraffe/n02439033_10453-6.png 3 +sketch/giraffe/n02439033_10491-1.png 3 +sketch/giraffe/n02439033_10491-2.png 3 +sketch/giraffe/n02439033_10491-3.png 3 +sketch/giraffe/n02439033_10491-4.png 3 +sketch/giraffe/n02439033_10491-5.png 3 +sketch/giraffe/n02439033_10491-6.png 3 +sketch/giraffe/n02439033_10541-1.png 3 +sketch/giraffe/n02439033_10541-2.png 3 +sketch/giraffe/n02439033_10541-3.png 3 +sketch/giraffe/n02439033_10541-4.png 3 +sketch/giraffe/n02439033_10541-5.png 3 +sketch/giraffe/n02439033_10541-6.png 3 +sketch/giraffe/n02439033_10616-1.png 3 +sketch/giraffe/n02439033_10616-2.png 3 +sketch/giraffe/n02439033_10616-3.png 3 +sketch/giraffe/n02439033_10616-4.png 3 +sketch/giraffe/n02439033_10616-5.png 3 +sketch/giraffe/n02439033_10802-1.png 3 +sketch/giraffe/n02439033_10802-2.png 3 +sketch/giraffe/n02439033_10802-3.png 3 +sketch/giraffe/n02439033_10802-4.png 3 +sketch/giraffe/n02439033_10802-5.png 3 +sketch/giraffe/n02439033_10802-6.png 3 +sketch/giraffe/n02439033_10802-7.png 3 +sketch/giraffe/n02439033_10802-8.png 3 +sketch/giraffe/n02439033_10803-1.png 3 +sketch/giraffe/n02439033_10803-2.png 3 +sketch/giraffe/n02439033_10803-3.png 3 +sketch/giraffe/n02439033_10803-4.png 3 +sketch/giraffe/n02439033_10803-5.png 3 +sketch/giraffe/n02439033_10811-1.png 3 +sketch/giraffe/n02439033_10811-2.png 3 +sketch/giraffe/n02439033_10811-3.png 3 +sketch/giraffe/n02439033_10811-4.png 3 +sketch/giraffe/n02439033_10811-5.png 3 +sketch/giraffe/n02439033_10811-6.png 3 +sketch/giraffe/n02439033_10811-7.png 3 +sketch/giraffe/n02439033_10839-1.png 3 +sketch/giraffe/n02439033_10839-2.png 3 +sketch/giraffe/n02439033_10839-3.png 3 +sketch/giraffe/n02439033_10839-4.png 3 +sketch/giraffe/n02439033_10839-5.png 3 +sketch/giraffe/n02439033_10839-6.png 3 +sketch/giraffe/n02439033_10839-7.png 3 +sketch/giraffe/n02439033_10919-1.png 3 +sketch/giraffe/n02439033_10919-2.png 3 +sketch/giraffe/n02439033_10919-3.png 3 +sketch/giraffe/n02439033_10919-4.png 3 +sketch/giraffe/n02439033_10919-5.png 3 +sketch/giraffe/n02439033_10919-6.png 3 +sketch/giraffe/n02439033_11059-1.png 3 +sketch/giraffe/n02439033_11059-2.png 3 +sketch/giraffe/n02439033_11059-3.png 3 +sketch/giraffe/n02439033_11059-4.png 3 +sketch/giraffe/n02439033_11059-5.png 3 +sketch/giraffe/n02439033_11059-6.png 3 +sketch/giraffe/n02439033_11059-7.png 3 +sketch/giraffe/n02439033_11059-8.png 3 +sketch/giraffe/n02439033_11059-9.png 3 +sketch/giraffe/n02439033_11114-1.png 3 +sketch/giraffe/n02439033_11114-2.png 3 +sketch/giraffe/n02439033_11114-3.png 3 +sketch/giraffe/n02439033_11114-4.png 3 +sketch/giraffe/n02439033_11114-5.png 3 +sketch/giraffe/n02439033_11130-1.png 3 +sketch/giraffe/n02439033_11130-2.png 3 +sketch/giraffe/n02439033_11130-3.png 3 +sketch/giraffe/n02439033_11130-4.png 3 +sketch/giraffe/n02439033_11130-5.png 3 +sketch/giraffe/n02439033_11130-6.png 3 +sketch/giraffe/n02439033_11215-1.png 3 +sketch/giraffe/n02439033_11215-2.png 3 +sketch/giraffe/n02439033_11215-3.png 3 +sketch/giraffe/n02439033_11215-4.png 3 +sketch/giraffe/n02439033_11215-5.png 3 +sketch/giraffe/n02439033_11273-1.png 3 +sketch/giraffe/n02439033_11273-2.png 3 +sketch/giraffe/n02439033_11273-3.png 3 +sketch/giraffe/n02439033_11273-4.png 3 +sketch/giraffe/n02439033_11273-5.png 3 +sketch/giraffe/n02439033_11273-6.png 3 +sketch/giraffe/n02439033_11328-1.png 3 +sketch/giraffe/n02439033_11328-2.png 3 +sketch/giraffe/n02439033_11328-3.png 3 +sketch/giraffe/n02439033_11328-4.png 3 +sketch/giraffe/n02439033_11328-5.png 3 +sketch/giraffe/n02439033_11328-6.png 3 +sketch/giraffe/n02439033_11458-1.png 3 +sketch/giraffe/n02439033_11458-2.png 3 +sketch/giraffe/n02439033_11458-3.png 3 +sketch/giraffe/n02439033_11458-4.png 3 +sketch/giraffe/n02439033_11458-5.png 3 +sketch/giraffe/n02439033_11458-6.png 3 +sketch/giraffe/n02439033_11486-1.png 3 +sketch/giraffe/n02439033_11486-2.png 3 +sketch/giraffe/n02439033_11486-3.png 3 +sketch/giraffe/n02439033_11486-4.png 3 +sketch/giraffe/n02439033_11486-5.png 3 +sketch/giraffe/n02439033_11487-1.png 3 +sketch/giraffe/n02439033_11487-2.png 3 +sketch/giraffe/n02439033_11487-3.png 3 +sketch/giraffe/n02439033_11487-4.png 3 +sketch/giraffe/n02439033_11487-5.png 3 +sketch/giraffe/n02439033_11487-6.png 3 +sketch/giraffe/n02439033_11487-7.png 3 +sketch/giraffe/n02439033_11504-1.png 3 +sketch/giraffe/n02439033_11504-2.png 3 +sketch/giraffe/n02439033_11504-3.png 3 +sketch/giraffe/n02439033_11504-4.png 3 +sketch/giraffe/n02439033_11504-5.png 3 +sketch/giraffe/n02439033_11504-6.png 3 +sketch/giraffe/n02439033_11504-7.png 3 +sketch/giraffe/n02439033_11599-1.png 3 +sketch/giraffe/n02439033_11599-2.png 3 +sketch/giraffe/n02439033_11599-3.png 3 +sketch/giraffe/n02439033_11599-4.png 3 +sketch/giraffe/n02439033_11599-5.png 3 +sketch/giraffe/n02439033_11599-6.png 3 +sketch/giraffe/n02439033_11599-7.png 3 +sketch/giraffe/n02439033_11599-8.png 3 +sketch/giraffe/n02439033_11627-1.png 3 +sketch/giraffe/n02439033_11627-2.png 3 +sketch/giraffe/n02439033_11627-3.png 3 +sketch/giraffe/n02439033_11627-4.png 3 +sketch/giraffe/n02439033_11627-5.png 3 +sketch/giraffe/n02439033_11627-6.png 3 +sketch/giraffe/n02439033_11627-7.png 3 +sketch/giraffe/n02439033_11666-1.png 3 +sketch/giraffe/n02439033_11666-2.png 3 +sketch/giraffe/n02439033_11666-3.png 3 +sketch/giraffe/n02439033_11666-4.png 3 +sketch/giraffe/n02439033_11666-5.png 3 +sketch/giraffe/n02439033_11666-6.png 3 +sketch/giraffe/n02439033_11666-7.png 3 +sketch/giraffe/n02439033_11683-1.png 3 +sketch/giraffe/n02439033_11683-2.png 3 +sketch/giraffe/n02439033_11683-3.png 3 +sketch/giraffe/n02439033_11683-4.png 3 +sketch/giraffe/n02439033_11683-5.png 3 +sketch/giraffe/n02439033_11683-6.png 3 +sketch/giraffe/n02439033_11683-7.png 3 +sketch/giraffe/n02439033_11715-1.png 3 +sketch/giraffe/n02439033_11715-2.png 3 +sketch/giraffe/n02439033_11715-3.png 3 +sketch/giraffe/n02439033_11715-4.png 3 +sketch/giraffe/n02439033_11715-5.png 3 +sketch/giraffe/n02439033_11715-6.png 3 +sketch/giraffe/n02439033_11845-1.png 3 +sketch/giraffe/n02439033_11845-2.png 3 +sketch/giraffe/n02439033_11845-3.png 3 +sketch/giraffe/n02439033_11845-4.png 3 +sketch/giraffe/n02439033_11845-5.png 3 +sketch/giraffe/n02439033_11845-6.png 3 +sketch/giraffe/n02439033_11845-7.png 3 +sketch/giraffe/n02439033_11845-8.png 3 +sketch/giraffe/n02439033_11845-9.png 3 +sketch/giraffe/n02439033_11845-10.png 3 +sketch/giraffe/n02439033_11894-1.png 3 +sketch/giraffe/n02439033_11894-2.png 3 +sketch/giraffe/n02439033_11894-3.png 3 +sketch/giraffe/n02439033_11894-4.png 3 +sketch/giraffe/n02439033_11894-5.png 3 +sketch/giraffe/n02439033_11894-6.png 3 +sketch/giraffe/n02439033_11894-7.png 3 +sketch/giraffe/n02439033_11894-8.png 3 +sketch/giraffe/n02439033_11894-9.png 3 +sketch/giraffe/n02439033_12059-1.png 3 +sketch/giraffe/n02439033_12059-2.png 3 +sketch/giraffe/n02439033_12059-3.png 3 +sketch/giraffe/n02439033_12059-4.png 3 +sketch/giraffe/n02439033_12059-5.png 3 +sketch/giraffe/n02439033_12413-1.png 3 +sketch/giraffe/n02439033_12413-2.png 3 +sketch/giraffe/n02439033_12413-3.png 3 +sketch/giraffe/n02439033_12413-4.png 3 +sketch/giraffe/n02439033_12413-5.png 3 +sketch/giraffe/n02439033_12413-6.png 3 +sketch/giraffe/n02439033_12413-7.png 3 +sketch/giraffe/n02439033_12485-1.png 3 +sketch/giraffe/n02439033_12485-2.png 3 +sketch/giraffe/n02439033_12485-3.png 3 +sketch/giraffe/n02439033_12485-4.png 3 +sketch/giraffe/n02439033_12485-5.png 3 +sketch/giraffe/n02439033_12485-6.png 3 +sketch/giraffe/n02439033_12680-1.png 3 +sketch/giraffe/n02439033_12680-2.png 3 +sketch/giraffe/n02439033_12680-3.png 3 +sketch/giraffe/n02439033_12680-4.png 3 +sketch/giraffe/n02439033_12680-5.png 3 +sketch/giraffe/n02439033_12930-1.png 3 +sketch/giraffe/n02439033_12930-2.png 3 +sketch/giraffe/n02439033_12930-3.png 3 +sketch/giraffe/n02439033_12930-4.png 3 +sketch/giraffe/n02439033_12930-5.png 3 +sketch/giraffe/n02439033_12939-1.png 3 +sketch/giraffe/n02439033_12939-2.png 3 +sketch/giraffe/n02439033_12939-3.png 3 +sketch/giraffe/n02439033_12939-4.png 3 +sketch/giraffe/n02439033_12939-5.png 3 +sketch/giraffe/n02439033_12939-6.png 3 +sketch/giraffe/n02439033_12939-7.png 3 +sketch/giraffe/n02439033_12939-8.png 3 +sketch/giraffe/n02439033_12987-1.png 3 +sketch/giraffe/n02439033_12987-2.png 3 +sketch/giraffe/n02439033_12987-3.png 3 +sketch/giraffe/n02439033_12987-4.png 3 +sketch/giraffe/n02439033_12987-5.png 3 +sketch/giraffe/n02439033_12987-6.png 3 +sketch/giraffe/n02439033_13236-1.png 3 +sketch/giraffe/n02439033_13236-2.png 3 +sketch/giraffe/n02439033_13236-3.png 3 +sketch/giraffe/n02439033_13236-4.png 3 +sketch/giraffe/n02439033_13236-5.png 3 +sketch/giraffe/n02439033_13236-6.png 3 +sketch/giraffe/n02439033_13384-1.png 3 +sketch/giraffe/n02439033_13384-2.png 3 +sketch/giraffe/n02439033_13384-3.png 3 +sketch/giraffe/n02439033_13384-4.png 3 +sketch/giraffe/n02439033_13384-5.png 3 +sketch/giraffe/n02439033_13384-6.png 3 +sketch/giraffe/n02439033_13430-1.png 3 +sketch/giraffe/n02439033_13430-2.png 3 +sketch/giraffe/n02439033_13430-3.png 3 +sketch/giraffe/n02439033_13430-4.png 3 +sketch/giraffe/n02439033_13430-5.png 3 +sketch/giraffe/n02439033_13602-1.png 3 +sketch/giraffe/n02439033_13602-2.png 3 +sketch/giraffe/n02439033_13602-3.png 3 +sketch/giraffe/n02439033_13602-4.png 3 +sketch/giraffe/n02439033_13602-5.png 3 +sketch/giraffe/n02439033_13602-6.png 3 +sketch/giraffe/n02439033_13602-7.png 3 +sketch/giraffe/n02439033_13868-1.png 3 +sketch/giraffe/n02439033_13868-2.png 3 +sketch/giraffe/n02439033_13868-3.png 3 +sketch/giraffe/n02439033_13868-4.png 3 +sketch/giraffe/n02439033_13868-5.png 3 +sketch/giraffe/n02439033_13868-6.png 3 +sketch/giraffe/n02439033_13868-7.png 3 +sketch/giraffe/n02439033_14040-1.png 3 +sketch/giraffe/n02439033_14040-2.png 3 +sketch/giraffe/n02439033_14040-3.png 3 +sketch/giraffe/n02439033_14040-4.png 3 +sketch/giraffe/n02439033_14040-5.png 3 +sketch/giraffe/n02439033_14040-6.png 3 +sketch/giraffe/n02439033_14060-1.png 3 +sketch/giraffe/n02439033_14060-2.png 3 +sketch/giraffe/n02439033_14060-3.png 3 +sketch/giraffe/n02439033_14060-4.png 3 +sketch/giraffe/n02439033_14060-5.png 3 +sketch/giraffe/n02439033_14060-6.png 3 +sketch/giraffe/n02439033_14060-7.png 3 +sketch/giraffe/n02439033_14060-8.png 3 +sketch/giraffe/n02439033_14121-1.png 3 +sketch/giraffe/n02439033_14121-2.png 3 +sketch/giraffe/n02439033_14121-3.png 3 +sketch/giraffe/n02439033_14121-4.png 3 +sketch/giraffe/n02439033_14121-5.png 3 +sketch/giraffe/n02439033_14121-6.png 3 +sketch/giraffe/n02439033_14121-7.png 3 +sketch/giraffe/n02439033_14121-8.png 3 +sketch/giraffe/n02439033_14121-9.png 3 +sketch/giraffe/n02439033_14121-10.png 3 +sketch/giraffe/n02439033_14148-1.png 3 +sketch/giraffe/n02439033_14148-2.png 3 +sketch/giraffe/n02439033_14148-3.png 3 +sketch/giraffe/n02439033_14148-4.png 3 +sketch/giraffe/n02439033_14148-5.png 3 +sketch/giraffe/n02439033_14148-6.png 3 +sketch/giraffe/n02439033_14148-7.png 3 +sketch/giraffe/n02439033_14148-8.png 3 +sketch/giraffe/n02439033_14148-9.png 3 +sketch/giraffe/n02439033_14148-10.png 3 +sketch/giraffe/n02439033_14184-1.png 3 +sketch/giraffe/n02439033_14184-2.png 3 +sketch/giraffe/n02439033_14184-3.png 3 +sketch/giraffe/7361.png 3 +sketch/giraffe/n02439033_14184-4.png 3 +sketch/giraffe/n02439033_14184-5.png 3 +sketch/giraffe/n02439033_14322-1.png 3 +sketch/giraffe/n02439033_14322-2.png 3 +sketch/giraffe/n02439033_14322-3.png 3 +sketch/giraffe/n02439033_14322-4.png 3 +sketch/giraffe/n02439033_14322-5.png 3 +sketch/giraffe/n02439033_14497-1.png 3 +sketch/giraffe/n02439033_14497-2.png 3 +sketch/giraffe/n02439033_14497-3.png 3 +sketch/giraffe/n02439033_14497-4.png 3 +sketch/giraffe/n02439033_14497-5.png 3 +sketch/giraffe/n02439033_14497-6.png 3 +sketch/giraffe/n02439033_14554-1.png 3 +sketch/giraffe/n02439033_14554-2.png 3 +sketch/giraffe/n02439033_14554-3.png 3 +sketch/giraffe/n02439033_14554-4.png 3 +sketch/giraffe/n02439033_14554-5.png 3 +sketch/giraffe/n02439033_14554-6.png 3 +sketch/giraffe/n02439033_14554-7.png 3 +sketch/giraffe/n02439033_14554-8.png 3 +sketch/giraffe/n02439033_14554-9.png 3 +sketch/giraffe/n02439033_14580-1.png 3 +sketch/giraffe/n02439033_14580-2.png 3 +sketch/giraffe/n02439033_14580-3.png 3 +sketch/giraffe/n02439033_14580-4.png 3 +sketch/giraffe/n02439033_14580-5.png 3 +sketch/giraffe/n02439033_14580-6.png 3 +sketch/giraffe/n02439033_14580-7.png 3 +sketch/giraffe/n02439033_14580-8.png 3 +sketch/giraffe/n02439033_14580-9.png 3 +sketch/giraffe/n02439033_14580-10.png 3 +sketch/giraffe/n02439033_14600-1.png 3 +sketch/giraffe/n02439033_14600-2.png 3 +sketch/giraffe/n02439033_14600-3.png 3 +sketch/giraffe/n02439033_14600-4.png 3 +sketch/giraffe/n02439033_14600-5.png 3 +sketch/giraffe/n02439033_14600-6.png 3 +sketch/giraffe/n02439033_14600-7.png 3 +sketch/giraffe/n02439033_14600-8.png 3 +sketch/giraffe/n02439033_14600-9.png 3 +sketch/giraffe/n02439033_14609-1.png 3 +sketch/giraffe/n02439033_14609-2.png 3 +sketch/giraffe/n02439033_14609-3.png 3 +sketch/giraffe/n02439033_14609-4.png 3 +sketch/giraffe/n02439033_14609-5.png 3 +sketch/giraffe/n02439033_14609-6.png 3 +sketch/giraffe/n02439033_14724-1.png 3 +sketch/giraffe/n02439033_14724-2.png 3 +sketch/giraffe/n02439033_14724-3.png 3 +sketch/giraffe/n02439033_14724-4.png 3 +sketch/giraffe/n02439033_14724-5.png 3 +sketch/giraffe/n02439033_14764-1.png 3 +sketch/giraffe/n02439033_14764-2.png 3 +sketch/giraffe/n02439033_14764-3.png 3 +sketch/giraffe/n02439033_14764-4.png 3 +sketch/giraffe/n02439033_14764-5.png 3 +sketch/giraffe/n02439033_14781-1.png 3 +sketch/giraffe/n02439033_14781-2.png 3 +sketch/giraffe/n02439033_14781-3.png 3 +sketch/giraffe/n02439033_14781-4.png 3 +sketch/giraffe/n02439033_14781-5.png 3 +sketch/giraffe/n02439033_14781-6.png 3 +sketch/giraffe/n02439033_14781-7.png 3 +sketch/giraffe/n02439033_14781-8.png 3 +sketch/giraffe/n02439033_14784-1.png 3 +sketch/giraffe/n02439033_14784-2.png 3 +sketch/giraffe/n02439033_14784-3.png 3 +sketch/giraffe/n02439033_14784-4.png 3 +sketch/giraffe/n02439033_14784-5.png 3 +sketch/giraffe/n02439033_14784-6.png 3 +sketch/giraffe/n02439033_14846-1.png 3 +sketch/giraffe/n02439033_14846-2.png 3 +sketch/giraffe/n02439033_14846-3.png 3 +sketch/giraffe/n02439033_14846-4.png 3 +sketch/giraffe/n02439033_14846-5.png 3 +sketch/giraffe/n02439033_14846-6.png 3 +sketch/giraffe/n02439033_14846-7.png 3 +sketch/giraffe/n02439033_14846-8.png 3 +sketch/giraffe/n02439033_14872-1.png 3 +sketch/giraffe/n02439033_14872-2.png 3 +sketch/giraffe/n02439033_14872-3.png 3 +sketch/giraffe/n02439033_14872-4.png 3 +sketch/giraffe/n02439033_14872-5.png 3 +sketch/giraffe/n02439033_14872-6.png 3 +sketch/giraffe/n02439033_14885-1.png 3 +sketch/giraffe/n02439033_14885-2.png 3 +sketch/giraffe/n02439033_14885-3.png 3 +sketch/giraffe/n02439033_14885-4.png 3 +sketch/giraffe/n02439033_14885-5.png 3 +sketch/giraffe/n02439033_14962-1.png 3 +sketch/giraffe/n02439033_14962-2.png 3 +sketch/giraffe/n02439033_14962-3.png 3 +sketch/giraffe/n02439033_14962-4.png 3 +sketch/giraffe/n02439033_14962-5.png 3 +sketch/giraffe/n02439033_14962-6.png 3 +sketch/giraffe/n02439033_14962-7.png 3 +sketch/giraffe/n02439033_15005-1.png 3 +sketch/giraffe/n02439033_15005-2.png 3 +sketch/giraffe/n02439033_15005-3.png 3 +sketch/giraffe/n02439033_15005-4.png 3 +sketch/giraffe/n02439033_15005-5.png 3 +sketch/giraffe/n02439033_15005-6.png 3 +sketch/giraffe/n02439033_15005-7.png 3 +sketch/giraffe/n02439033_15005-8.png 3 +sketch/giraffe/n02439033_15005-9.png 3 +sketch/giraffe/n02439033_15005-10.png 3 +sketch/giraffe/n02439033_15384-1.png 3 +sketch/giraffe/n02439033_15384-2.png 3 +sketch/giraffe/n02439033_15384-3.png 3 +sketch/giraffe/n02439033_15384-4.png 3 +sketch/giraffe/n02439033_15384-5.png 3 +sketch/giraffe/n02439033_15401-1.png 3 +sketch/giraffe/n02439033_15401-2.png 3 +sketch/giraffe/n02439033_15401-3.png 3 +sketch/giraffe/n02439033_15401-4.png 3 +sketch/giraffe/n02439033_15401-5.png 3 +sketch/giraffe/n02439033_15453-1.png 3 +sketch/giraffe/n02439033_15453-2.png 3 +sketch/giraffe/n02439033_15453-3.png 3 +sketch/giraffe/n02439033_15453-4.png 3 +sketch/giraffe/n02439033_15453-5.png 3 +sketch/giraffe/n02439033_15453-6.png 3 +sketch/giraffe/n02439033_15453-7.png 3 +sketch/giraffe/n02439033_15453-8.png 3 +sketch/giraffe/n02439033_15453-9.png 3 +sketch/giraffe/n02439033_15479-1.png 3 +sketch/giraffe/n02439033_15479-2.png 3 +sketch/giraffe/n02439033_15479-3.png 3 +sketch/giraffe/n02439033_15479-4.png 3 +sketch/giraffe/n02439033_15479-5.png 3 +sketch/giraffe/n02439033_15479-6.png 3 +sketch/giraffe/n02439033_15479-7.png 3 +sketch/giraffe/n02439033_15540-1.png 3 +sketch/giraffe/n02439033_15540-2.png 3 +sketch/giraffe/n02439033_15540-3.png 3 +sketch/giraffe/n02439033_15540-4.png 3 +sketch/giraffe/n02439033_15540-5.png 3 +sketch/giraffe/n02439033_15540-6.png 3 +sketch/giraffe/n02439033_15555-1.png 3 +sketch/giraffe/n02439033_15555-2.png 3 +sketch/giraffe/n02439033_15555-3.png 3 +sketch/giraffe/n02439033_15555-4.png 3 +sketch/giraffe/n02439033_15555-5.png 3 +sketch/giraffe/n02439033_15936-1.png 3 +sketch/giraffe/n02439033_15936-2.png 3 +sketch/giraffe/n02439033_15936-3.png 3 +sketch/giraffe/n02439033_15936-4.png 3 +sketch/giraffe/n02439033_15936-5.png 3 +sketch/giraffe/n02439033_15936-6.png 3 +sketch/giraffe/n02439033_15936-7.png 3 +sketch/giraffe/n02439033_16085-1.png 3 +sketch/giraffe/n02439033_16085-2.png 3 +sketch/giraffe/n02439033_16085-3.png 3 +sketch/giraffe/n02439033_16085-4.png 3 +sketch/giraffe/n02439033_16085-5.png 3 +sketch/giraffe/n02439033_16356-1.png 3 +sketch/giraffe/n02439033_16356-2.png 3 +sketch/giraffe/n02439033_16356-3.png 3 +sketch/giraffe/n02439033_16356-4.png 3 +sketch/giraffe/n02439033_16356-5.png 3 +sketch/giraffe/n02439033_16483-1.png 3 +sketch/giraffe/n02439033_16483-2.png 3 +sketch/giraffe/n02439033_16483-3.png 3 +sketch/giraffe/n02439033_16483-4.png 3 +sketch/giraffe/n02439033_16483-5.png 3 +sketch/giraffe/n02439033_16483-6.png 3 +sketch/giraffe/7362.png 3 +sketch/giraffe/7363.png 3 +sketch/giraffe/7364.png 3 +sketch/giraffe/7365.png 3 +sketch/giraffe/7366.png 3 +sketch/giraffe/7367.png 3 +sketch/giraffe/7368.png 3 +sketch/giraffe/7369.png 3 +sketch/giraffe/7370.png 3 +sketch/giraffe/7371.png 3 +sketch/giraffe/7372.png 3 +sketch/giraffe/7373.png 3 +sketch/giraffe/7374.png 3 +sketch/giraffe/7375.png 3 +sketch/giraffe/7376.png 3 +sketch/giraffe/7377.png 3 +sketch/giraffe/7378.png 3 +sketch/giraffe/7379.png 3 +sketch/giraffe/7380.png 3 +sketch/giraffe/7381.png 3 +sketch/giraffe/7382.png 3 +sketch/giraffe/7383.png 3 +sketch/giraffe/7384.png 3 +sketch/giraffe/7385.png 3 +sketch/giraffe/7386.png 3 +sketch/giraffe/7387.png 3 +sketch/giraffe/7388.png 3 +sketch/giraffe/7389.png 3 +sketch/giraffe/7390.png 3 +sketch/giraffe/7391.png 3 +sketch/giraffe/7392.png 3 +sketch/giraffe/7393.png 3 +sketch/giraffe/7394.png 3 +sketch/giraffe/7395.png 3 +sketch/giraffe/7396.png 3 +sketch/giraffe/7397.png 3 +sketch/giraffe/7398.png 3 +sketch/giraffe/7399.png 3 +sketch/giraffe/7400.png 3 +sketch/giraffe/7401.png 3 +sketch/giraffe/7402.png 3 +sketch/giraffe/7403.png 3 +sketch/giraffe/7404.png 3 +sketch/giraffe/7405.png 3 +sketch/giraffe/7406.png 3 +sketch/giraffe/7407.png 3 +sketch/giraffe/7408.png 3 +sketch/giraffe/7409.png 3 +sketch/giraffe/7410.png 3 +sketch/giraffe/7411.png 3 +sketch/giraffe/7412.png 3 +sketch/giraffe/7413.png 3 +sketch/giraffe/7414.png 3 +sketch/giraffe/7415.png 3 +sketch/giraffe/7416.png 3 +sketch/giraffe/7417.png 3 +sketch/giraffe/7418.png 3 +sketch/giraffe/7419.png 3 +sketch/giraffe/7420.png 3 +sketch/giraffe/7421.png 3 +sketch/giraffe/7422.png 3 +sketch/giraffe/7423.png 3 +sketch/giraffe/7424.png 3 +sketch/giraffe/7425.png 3 +sketch/giraffe/7426.png 3 +sketch/giraffe/7427.png 3 +sketch/giraffe/7428.png 3 +sketch/giraffe/7429.png 3 +sketch/giraffe/7430.png 3 +sketch/giraffe/7431.png 3 +sketch/giraffe/7432.png 3 +sketch/giraffe/7433.png 3 +sketch/giraffe/7434.png 3 +sketch/giraffe/7435.png 3 +sketch/giraffe/7436.png 3 +sketch/giraffe/7437.png 3 +sketch/giraffe/7438.png 3 +sketch/giraffe/7439.png 3 +sketch/giraffe/7440.png 3 +sketch/guitar/7662.png 4 +sketch/guitar/7663.png 4 +sketch/guitar/7664.png 4 +sketch/guitar/7665.png 4 +sketch/guitar/7666.png 4 +sketch/guitar/7667.png 4 +sketch/guitar/7668.png 4 +sketch/guitar/7669.png 4 +sketch/guitar/7670.png 4 +sketch/guitar/7671.png 4 +sketch/guitar/7672.png 4 +sketch/guitar/7673.png 4 +sketch/guitar/7674.png 4 +sketch/guitar/7675.png 4 +sketch/guitar/7676.png 4 +sketch/guitar/7677.png 4 +sketch/guitar/7678.png 4 +sketch/guitar/7679.png 4 +sketch/guitar/7680.png 4 +sketch/guitar/n02676566_307-1.png 4 +sketch/guitar/n02676566_307-2.png 4 +sketch/guitar/n02676566_307-3.png 4 +sketch/guitar/n02676566_307-4.png 4 +sketch/guitar/n02676566_307-5.png 4 +sketch/guitar/n02676566_330-1.png 4 +sketch/guitar/n02676566_330-2.png 4 +sketch/guitar/n02676566_330-3.png 4 +sketch/guitar/n02676566_330-4.png 4 +sketch/guitar/n02676566_330-5.png 4 +sketch/guitar/n02676566_330-6.png 4 +sketch/guitar/n02676566_659-1.png 4 +sketch/guitar/n02676566_659-2.png 4 +sketch/guitar/n02676566_659-3.png 4 +sketch/guitar/n02676566_659-4.png 4 +sketch/guitar/n02676566_659-5.png 4 +sketch/guitar/n02676566_970-1.png 4 +sketch/guitar/n02676566_970-2.png 4 +sketch/guitar/n02676566_970-3.png 4 +sketch/guitar/n02676566_970-4.png 4 +sketch/guitar/n02676566_970-5.png 4 +sketch/guitar/n02676566_970-6.png 4 +sketch/guitar/n02676566_1324-1.png 4 +sketch/guitar/n02676566_1324-2.png 4 +sketch/guitar/n02676566_1324-3.png 4 +sketch/guitar/n02676566_1324-4.png 4 +sketch/guitar/n02676566_1324-5.png 4 +sketch/guitar/n02676566_2380-1.png 4 +sketch/guitar/n02676566_2380-2.png 4 +sketch/guitar/n02676566_2380-3.png 4 +sketch/guitar/n02676566_2380-4.png 4 +sketch/guitar/n02676566_2380-5.png 4 +sketch/guitar/n02676566_2866-1.png 4 +sketch/guitar/n02676566_2866-2.png 4 +sketch/guitar/n02676566_2866-3.png 4 +sketch/guitar/n02676566_2866-4.png 4 +sketch/guitar/n02676566_2866-5.png 4 +sketch/guitar/n02676566_3360-1.png 4 +sketch/guitar/n02676566_3360-2.png 4 +sketch/guitar/n02676566_3360-3.png 4 +sketch/guitar/n02676566_3360-4.png 4 +sketch/guitar/n02676566_3360-5.png 4 +sketch/guitar/n02676566_3360-6.png 4 +sketch/guitar/n02676566_4058-1.png 4 +sketch/guitar/n02676566_4058-2.png 4 +sketch/guitar/n02676566_4058-3.png 4 +sketch/guitar/n02676566_4058-4.png 4 +sketch/guitar/n02676566_4058-5.png 4 +sketch/guitar/n02676566_4058-6.png 4 +sketch/guitar/n02676566_4189-1.png 4 +sketch/guitar/n02676566_4189-2.png 4 +sketch/guitar/n02676566_4189-3.png 4 +sketch/guitar/n02676566_4189-4.png 4 +sketch/guitar/n02676566_4189-5.png 4 +sketch/guitar/n02676566_4469-1.png 4 +sketch/guitar/n02676566_4469-2.png 4 +sketch/guitar/n02676566_4469-3.png 4 +sketch/guitar/n02676566_4469-4.png 4 +sketch/guitar/n02676566_4469-5.png 4 +sketch/guitar/n02676566_4605-1.png 4 +sketch/guitar/n02676566_4605-2.png 4 +sketch/guitar/n02676566_4605-3.png 4 +sketch/guitar/n02676566_4605-4.png 4 +sketch/guitar/n02676566_4605-5.png 4 +sketch/guitar/n02676566_4605-6.png 4 +sketch/guitar/n02676566_4699-1.png 4 +sketch/guitar/n02676566_4699-2.png 4 +sketch/guitar/n02676566_4699-3.png 4 +sketch/guitar/n02676566_4699-4.png 4 +sketch/guitar/n02676566_4699-5.png 4 +sketch/guitar/n02676566_5134-1.png 4 +sketch/guitar/n02676566_5134-2.png 4 +sketch/guitar/n02676566_5134-3.png 4 +sketch/guitar/n02676566_5134-4.png 4 +sketch/guitar/n02676566_5134-5.png 4 +sketch/guitar/n02676566_5489-1.png 4 +sketch/guitar/n02676566_5489-2.png 4 +sketch/guitar/n02676566_5489-3.png 4 +sketch/guitar/n02676566_5489-4.png 4 +sketch/guitar/n02676566_5489-5.png 4 +sketch/guitar/n02676566_5489-6.png 4 +sketch/guitar/n02676566_5489-7.png 4 +sketch/guitar/n02676566_5735-1.png 4 +sketch/guitar/n02676566_5735-2.png 4 +sketch/guitar/n02676566_5735-3.png 4 +sketch/guitar/n02676566_5735-4.png 4 +sketch/guitar/n02676566_5735-5.png 4 +sketch/guitar/n02676566_6150-1.png 4 +sketch/guitar/n02676566_6150-2.png 4 +sketch/guitar/n02676566_6150-3.png 4 +sketch/guitar/n02676566_6150-4.png 4 +sketch/guitar/n02676566_6150-5.png 4 +sketch/guitar/n02676566_6402-1.png 4 +sketch/guitar/n02676566_6402-2.png 4 +sketch/guitar/n02676566_6402-3.png 4 +sketch/guitar/n02676566_6402-4.png 4 +sketch/guitar/n02676566_6402-5.png 4 +sketch/guitar/n02676566_6430-1.png 4 +sketch/guitar/n02676566_6430-2.png 4 +sketch/guitar/n02676566_6430-3.png 4 +sketch/guitar/n02676566_6430-4.png 4 +sketch/guitar/n02676566_6430-5.png 4 +sketch/guitar/n02676566_6560-1.png 4 +sketch/guitar/n02676566_6560-2.png 4 +sketch/guitar/n02676566_6560-3.png 4 +sketch/guitar/n02676566_6560-4.png 4 +sketch/guitar/n02676566_6560-5.png 4 +sketch/guitar/n02676566_6631-1.png 4 +sketch/guitar/n02676566_6631-2.png 4 +sketch/guitar/n02676566_6631-3.png 4 +sketch/guitar/n02676566_6631-4.png 4 +sketch/guitar/n02676566_6631-5.png 4 +sketch/guitar/n02676566_6704-1.png 4 +sketch/guitar/n02676566_6704-2.png 4 +sketch/guitar/n02676566_6704-3.png 4 +sketch/guitar/n02676566_6704-4.png 4 +sketch/guitar/n02676566_6704-5.png 4 +sketch/guitar/n02676566_6864-1.png 4 +sketch/guitar/n02676566_6864-2.png 4 +sketch/guitar/n02676566_6864-3.png 4 +sketch/guitar/n02676566_6864-4.png 4 +sketch/guitar/n02676566_6864-5.png 4 +sketch/guitar/n02676566_6914-1.png 4 +sketch/guitar/n02676566_6914-2.png 4 +sketch/guitar/n02676566_6914-3.png 4 +sketch/guitar/n02676566_6914-4.png 4 +sketch/guitar/n02676566_6914-5.png 4 +sketch/guitar/n02676566_6948-1.png 4 +sketch/guitar/n02676566_6948-2.png 4 +sketch/guitar/n02676566_6948-3.png 4 +sketch/guitar/n02676566_6948-4.png 4 +sketch/guitar/n02676566_6948-5.png 4 +sketch/guitar/n02676566_6980-1.png 4 +sketch/guitar/n02676566_6980-2.png 4 +sketch/guitar/n02676566_6980-3.png 4 +sketch/guitar/n02676566_6980-4.png 4 +sketch/guitar/n02676566_6980-5.png 4 +sketch/guitar/n02676566_7385-1.png 4 +sketch/guitar/n02676566_7385-2.png 4 +sketch/guitar/n02676566_7385-3.png 4 +sketch/guitar/n02676566_7385-4.png 4 +sketch/guitar/n02676566_7385-5.png 4 +sketch/guitar/n02676566_7385-6.png 4 +sketch/guitar/n02676566_7770-1.png 4 +sketch/guitar/n02676566_7770-2.png 4 +sketch/guitar/n02676566_7770-3.png 4 +sketch/guitar/n02676566_7770-4.png 4 +sketch/guitar/n02676566_7770-5.png 4 +sketch/guitar/n02676566_7830-1.png 4 +sketch/guitar/n02676566_7830-2.png 4 +sketch/guitar/n02676566_7830-3.png 4 +sketch/guitar/n02676566_7830-4.png 4 +sketch/guitar/n02676566_7830-5.png 4 +sketch/guitar/n02676566_7844-1.png 4 +sketch/guitar/n02676566_7844-2.png 4 +sketch/guitar/n02676566_7844-3.png 4 +sketch/guitar/n02676566_7844-4.png 4 +sketch/guitar/n02676566_7844-5.png 4 +sketch/guitar/n02676566_7927-1.png 4 +sketch/guitar/n02676566_7927-2.png 4 +sketch/guitar/n02676566_7927-3.png 4 +sketch/guitar/n02676566_7927-4.png 4 +sketch/guitar/n02676566_7927-5.png 4 +sketch/guitar/n02676566_7927-6.png 4 +sketch/guitar/n02676566_8268-1.png 4 +sketch/guitar/n02676566_8268-2.png 4 +sketch/guitar/n02676566_8268-3.png 4 +sketch/guitar/n02676566_8268-4.png 4 +sketch/guitar/n02676566_8268-5.png 4 +sketch/guitar/n02676566_8309-1.png 4 +sketch/guitar/n02676566_8309-2.png 4 +sketch/guitar/n02676566_8309-3.png 4 +sketch/guitar/n02676566_8309-4.png 4 +sketch/guitar/n02676566_8309-5.png 4 +sketch/guitar/n02676566_8467-1.png 4 +sketch/guitar/n02676566_8467-2.png 4 +sketch/guitar/n02676566_8467-3.png 4 +sketch/guitar/n02676566_8467-4.png 4 +sketch/guitar/n02676566_8467-5.png 4 +sketch/guitar/n02676566_8618-1.png 4 +sketch/guitar/n02676566_8618-2.png 4 +sketch/guitar/n02676566_8618-3.png 4 +sketch/guitar/n02676566_8618-4.png 4 +sketch/guitar/n02676566_8618-5.png 4 +sketch/guitar/n02676566_8618-6.png 4 +sketch/guitar/n02676566_8820-1.png 4 +sketch/guitar/n02676566_8820-2.png 4 +sketch/guitar/n02676566_8820-3.png 4 +sketch/guitar/n02676566_8820-4.png 4 +sketch/guitar/n02676566_8820-5.png 4 +sketch/guitar/n02676566_8859-1.png 4 +sketch/guitar/n02676566_8859-2.png 4 +sketch/guitar/n02676566_8859-3.png 4 +sketch/guitar/n02676566_8859-4.png 4 +sketch/guitar/n02676566_8859-5.png 4 +sketch/guitar/n02676566_8859-6.png 4 +sketch/guitar/n02676566_8997-1.png 4 +sketch/guitar/n02676566_8997-2.png 4 +sketch/guitar/n02676566_8997-3.png 4 +sketch/guitar/n02676566_8997-4.png 4 +sketch/guitar/n02676566_8997-5.png 4 +sketch/guitar/n02676566_9062-1.png 4 +sketch/guitar/n02676566_9062-2.png 4 +sketch/guitar/n02676566_9062-3.png 4 +sketch/guitar/n02676566_9062-4.png 4 +sketch/guitar/n02676566_9062-5.png 4 +sketch/guitar/n02676566_9243-1.png 4 +sketch/guitar/n02676566_9243-2.png 4 +sketch/guitar/n02676566_9243-3.png 4 +sketch/guitar/n02676566_9243-4.png 4 +sketch/guitar/n02676566_9243-5.png 4 +sketch/guitar/n02676566_9243-6.png 4 +sketch/guitar/n02676566_9254-1.png 4 +sketch/guitar/n02676566_9254-2.png 4 +sketch/guitar/n02676566_9254-3.png 4 +sketch/guitar/n02676566_9254-4.png 4 +sketch/guitar/n02676566_9254-5.png 4 +sketch/guitar/n02676566_9451-1.png 4 +sketch/guitar/n02676566_9451-2.png 4 +sketch/guitar/n02676566_9451-3.png 4 +sketch/guitar/n02676566_9451-4.png 4 +sketch/guitar/n02676566_9451-5.png 4 +sketch/guitar/n02676566_9577-1.png 4 +sketch/guitar/n02676566_9577-2.png 4 +sketch/guitar/n02676566_9577-3.png 4 +sketch/guitar/n02676566_9577-4.png 4 +sketch/guitar/n02676566_9577-5.png 4 +sketch/guitar/n02676566_9577-6.png 4 +sketch/guitar/n02676566_9612-1.png 4 +sketch/guitar/n02676566_9612-2.png 4 +sketch/guitar/n02676566_9612-3.png 4 +sketch/guitar/n02676566_9612-4.png 4 +sketch/guitar/n02676566_9612-5.png 4 +sketch/guitar/n02676566_9661-1.png 4 +sketch/guitar/n02676566_9661-2.png 4 +sketch/guitar/n02676566_9661-3.png 4 +sketch/guitar/n02676566_9661-4.png 4 +sketch/guitar/n02676566_9661-5.png 4 +sketch/guitar/n02676566_9661-6.png 4 +sketch/guitar/n02676566_9936-1.png 4 +sketch/guitar/n02676566_9936-2.png 4 +sketch/guitar/n02676566_9936-3.png 4 +sketch/guitar/n02676566_9936-4.png 4 +sketch/guitar/n02676566_9936-5.png 4 +sketch/guitar/n02676566_11377-1.png 4 +sketch/guitar/n02676566_11377-2.png 4 +sketch/guitar/n02676566_11377-3.png 4 +sketch/guitar/n02676566_11377-4.png 4 +sketch/guitar/n02676566_11377-5.png 4 +sketch/guitar/n02676566_11573-1.png 4 +sketch/guitar/n02676566_11573-2.png 4 +sketch/guitar/n02676566_11573-3.png 4 +sketch/guitar/n02676566_11573-4.png 4 +sketch/guitar/n02676566_11573-5.png 4 +sketch/guitar/n02676566_12344-1.png 4 +sketch/guitar/n02676566_12344-2.png 4 +sketch/guitar/n02676566_12344-3.png 4 +sketch/guitar/n02676566_12344-4.png 4 +sketch/guitar/n02676566_12344-5.png 4 +sketch/guitar/n03272010_392-1.png 4 +sketch/guitar/n03272010_392-2.png 4 +sketch/guitar/n03272010_392-3.png 4 +sketch/guitar/n03272010_392-4.png 4 +sketch/guitar/n03272010_392-5.png 4 +sketch/guitar/n03272010_446-1.png 4 +sketch/guitar/n03272010_446-2.png 4 +sketch/guitar/n03272010_446-3.png 4 +sketch/guitar/n03272010_446-4.png 4 +sketch/guitar/n03272010_446-5.png 4 +sketch/guitar/n03272010_1708-1.png 4 +sketch/guitar/n03272010_1708-2.png 4 +sketch/guitar/n03272010_1708-3.png 4 +sketch/guitar/n03272010_1708-4.png 4 +sketch/guitar/n03272010_1708-5.png 4 +sketch/guitar/n03272010_1708-6.png 4 +sketch/guitar/n03272010_3732-1.png 4 +sketch/guitar/n03272010_3732-2.png 4 +sketch/guitar/n03272010_3732-3.png 4 +sketch/guitar/n03272010_3732-4.png 4 +sketch/guitar/n03272010_3732-5.png 4 +sketch/guitar/n03272010_3732-6.png 4 +sketch/guitar/n03272010_5483-1.png 4 +sketch/guitar/n03272010_5483-2.png 4 +sketch/guitar/n03272010_5483-3.png 4 +sketch/guitar/n03272010_5483-4.png 4 +sketch/guitar/n03272010_5483-5.png 4 +sketch/guitar/n03272010_5483-6.png 4 +sketch/guitar/n03272010_5875-1.png 4 +sketch/guitar/n03272010_5875-2.png 4 +sketch/guitar/n03272010_5875-3.png 4 +sketch/guitar/n03272010_5875-4.png 4 +sketch/guitar/n03272010_5875-5.png 4 +sketch/guitar/n03272010_5887-1.png 4 +sketch/guitar/n03272010_5887-2.png 4 +sketch/guitar/n03272010_5887-3.png 4 +sketch/guitar/n03272010_5887-4.png 4 +sketch/guitar/n03272010_5887-5.png 4 +sketch/guitar/n03272010_5887-6.png 4 +sketch/guitar/n03272010_5887-7.png 4 +sketch/guitar/n03272010_6152-1.png 4 +sketch/guitar/n03272010_6152-2.png 4 +sketch/guitar/n03272010_6152-3.png 4 +sketch/guitar/n03272010_6152-4.png 4 +sketch/guitar/n03272010_6152-5.png 4 +sketch/guitar/n03272010_6255-1.png 4 +sketch/guitar/n03272010_6255-2.png 4 +sketch/guitar/n03272010_6255-3.png 4 +sketch/guitar/n03272010_6255-4.png 4 +sketch/guitar/n03272010_6255-5.png 4 +sketch/guitar/n03272010_6291-1.png 4 +sketch/guitar/n03272010_6291-2.png 4 +sketch/guitar/n03272010_6291-3.png 4 +sketch/guitar/n03272010_6291-4.png 4 +sketch/guitar/n03272010_6291-5.png 4 +sketch/guitar/n03272010_6650-1.png 4 +sketch/guitar/n03272010_6650-2.png 4 +sketch/guitar/n03272010_6650-3.png 4 +sketch/guitar/n03272010_6650-4.png 4 +sketch/guitar/n03272010_6650-5.png 4 +sketch/guitar/n03272010_6650-6.png 4 +sketch/guitar/n03272010_6662-1.png 4 +sketch/guitar/n03272010_6662-2.png 4 +sketch/guitar/n03272010_6662-3.png 4 +sketch/guitar/n03272010_6662-4.png 4 +sketch/guitar/n03272010_6662-5.png 4 +sketch/guitar/n03272010_6662-6.png 4 +sketch/guitar/n03272010_6662-7.png 4 +sketch/guitar/n03272010_6718-1.png 4 +sketch/guitar/n03272010_6718-2.png 4 +sketch/guitar/n03272010_6718-3.png 4 +sketch/guitar/n03272010_6718-4.png 4 +sketch/guitar/n03272010_6718-5.png 4 +sketch/guitar/n03272010_6725-1.png 4 +sketch/guitar/n03272010_6725-2.png 4 +sketch/guitar/n03272010_6725-3.png 4 +sketch/guitar/n03272010_6725-4.png 4 +sketch/guitar/n03272010_6725-5.png 4 +sketch/guitar/n03272010_6727-1.png 4 +sketch/guitar/n03272010_6727-2.png 4 +sketch/guitar/n03272010_6727-3.png 4 +sketch/guitar/n03272010_6727-4.png 4 +sketch/guitar/n03272010_6727-5.png 4 +sketch/guitar/n03272010_6737-1.png 4 +sketch/guitar/n03272010_6737-2.png 4 +sketch/guitar/n03272010_6737-3.png 4 +sketch/guitar/n03272010_6737-4.png 4 +sketch/guitar/n03272010_6737-5.png 4 +sketch/guitar/n03272010_6737-6.png 4 +sketch/guitar/n03272010_6799-1.png 4 +sketch/guitar/n03272010_6799-2.png 4 +sketch/guitar/n03272010_6799-3.png 4 +sketch/guitar/n03272010_6799-4.png 4 +sketch/guitar/n03272010_6799-5.png 4 +sketch/guitar/n03272010_6809-1.png 4 +sketch/guitar/n03272010_6809-2.png 4 +sketch/guitar/n03272010_6809-3.png 4 +sketch/guitar/n03272010_6809-4.png 4 +sketch/guitar/n03272010_6809-5.png 4 +sketch/guitar/n03272010_6820-1.png 4 +sketch/guitar/n03272010_6820-2.png 4 +sketch/guitar/n03272010_6820-3.png 4 +sketch/guitar/n03272010_6820-4.png 4 +sketch/guitar/n03272010_6820-5.png 4 +sketch/guitar/n03272010_6926-1.png 4 +sketch/guitar/n03272010_6926-2.png 4 +sketch/guitar/n03272010_6926-3.png 4 +sketch/guitar/n03272010_6926-4.png 4 +sketch/guitar/n03272010_6926-5.png 4 +sketch/guitar/n03272010_7000-1.png 4 +sketch/guitar/n03272010_7000-2.png 4 +sketch/guitar/n03272010_7000-3.png 4 +sketch/guitar/n03272010_7000-4.png 4 +sketch/guitar/n03272010_7000-5.png 4 +sketch/guitar/n03272010_7092-1.png 4 +sketch/guitar/n03272010_7092-2.png 4 +sketch/guitar/n03272010_7092-3.png 4 +sketch/guitar/n03272010_7092-4.png 4 +sketch/guitar/n03272010_7092-5.png 4 +sketch/guitar/n03272010_7383-1.png 4 +sketch/guitar/n03272010_7383-2.png 4 +sketch/guitar/n03272010_7383-3.png 4 +sketch/guitar/n03272010_7383-4.png 4 +sketch/guitar/n03272010_7383-5.png 4 +sketch/guitar/n03272010_7390-1.png 4 +sketch/guitar/n03272010_7390-2.png 4 +sketch/guitar/n03272010_7390-3.png 4 +sketch/guitar/n03272010_7390-4.png 4 +sketch/guitar/n03272010_7390-5.png 4 +sketch/guitar/n03272010_7635-1.png 4 +sketch/guitar/n03272010_7635-2.png 4 +sketch/guitar/n03272010_7635-3.png 4 +sketch/guitar/n03272010_7635-4.png 4 +sketch/guitar/n03272010_7635-5.png 4 +sketch/guitar/n03272010_7729-1.png 4 +sketch/guitar/n03272010_7729-2.png 4 +sketch/guitar/n03272010_7729-3.png 4 +sketch/guitar/n03272010_7729-4.png 4 +sketch/guitar/n03272010_7729-5.png 4 +sketch/guitar/n03272010_9557-1.png 4 +sketch/guitar/n03272010_9557-2.png 4 +sketch/guitar/n03272010_9557-3.png 4 +sketch/guitar/n03272010_9557-4.png 4 +sketch/guitar/n03272010_9557-5.png 4 +sketch/guitar/n03272010_9557-6.png 4 +sketch/guitar/n03272010_9858-1.png 4 +sketch/guitar/n03272010_9858-2.png 4 +sketch/guitar/n03272010_9858-3.png 4 +sketch/guitar/n03272010_9858-4.png 4 +sketch/guitar/n03272010_9858-5.png 4 +sketch/guitar/n03272010_9899-1.png 4 +sketch/guitar/n03272010_9899-2.png 4 +sketch/guitar/n03272010_9899-3.png 4 +sketch/guitar/n03272010_9899-4.png 4 +sketch/guitar/n03272010_9899-5.png 4 +sketch/guitar/n03272010_10441-1.png 4 +sketch/guitar/n03272010_10441-2.png 4 +sketch/guitar/n03272010_10441-3.png 4 +sketch/guitar/n03272010_10441-4.png 4 +sketch/guitar/n03272010_10441-5.png 4 +sketch/guitar/n03272010_10795-1.png 4 +sketch/guitar/n03272010_10795-2.png 4 +sketch/guitar/n03272010_10795-3.png 4 +sketch/guitar/n03272010_10795-4.png 4 +sketch/guitar/n03272010_10795-5.png 4 +sketch/guitar/n03272010_11646-1.png 4 +sketch/guitar/n03272010_11646-2.png 4 +sketch/guitar/n03272010_11646-3.png 4 +sketch/guitar/n03272010_11646-4.png 4 +sketch/guitar/n03272010_11646-5.png 4 +sketch/guitar/n03272010_12151-1.png 4 +sketch/guitar/n03272010_12151-2.png 4 +sketch/guitar/n03272010_12151-3.png 4 +sketch/guitar/n03272010_12151-4.png 4 +sketch/guitar/n03272010_12151-5.png 4 +sketch/guitar/n03272010_12468-1.png 4 +sketch/guitar/n03272010_12468-2.png 4 +sketch/guitar/n03272010_12468-3.png 4 +sketch/guitar/n03272010_12468-4.png 4 +sketch/guitar/n03272010_12468-5.png 4 +sketch/guitar/n03467517_3203-1.png 4 +sketch/guitar/n03467517_3203-2.png 4 +sketch/guitar/n03467517_3203-3.png 4 +sketch/guitar/n03467517_3203-4.png 4 +sketch/guitar/n03467517_3203-5.png 4 +sketch/guitar/n03467517_6423-1.png 4 +sketch/guitar/n03467517_6423-2.png 4 +sketch/guitar/n03467517_6423-3.png 4 +sketch/guitar/n03467517_6423-4.png 4 +sketch/guitar/n03467517_6423-5.png 4 +sketch/guitar/n03467517_7007-1.png 4 +sketch/guitar/n03467517_7007-2.png 4 +sketch/guitar/n03467517_7007-3.png 4 +sketch/guitar/n03467517_7007-4.png 4 +sketch/guitar/n03467517_7007-5.png 4 +sketch/guitar/n03467517_7007-6.png 4 +sketch/guitar/n03467517_8929-1.png 4 +sketch/guitar/n03467517_8929-2.png 4 +sketch/guitar/n03467517_8929-3.png 4 +sketch/guitar/n03467517_8929-4.png 4 +sketch/guitar/n03467517_8929-5.png 4 +sketch/guitar/n03467517_11020-1.png 4 +sketch/guitar/n03467517_11020-2.png 4 +sketch/guitar/n03467517_11020-3.png 4 +sketch/guitar/n03467517_11020-4.png 4 +sketch/guitar/n03467517_11020-5.png 4 +sketch/guitar/n03467517_12925-1.png 4 +sketch/guitar/n03467517_12925-2.png 4 +sketch/guitar/n03467517_12925-3.png 4 +sketch/guitar/n03467517_12925-4.png 4 +sketch/guitar/n03467517_12925-5.png 4 +sketch/guitar/n03467517_16911-1.png 4 +sketch/guitar/n03467517_16911-2.png 4 +sketch/guitar/n03467517_16911-3.png 4 +sketch/guitar/n03467517_16911-4.png 4 +sketch/guitar/n03467517_16911-5.png 4 +sketch/guitar/n03467517_17233-1.png 4 +sketch/guitar/n03467517_17233-2.png 4 +sketch/guitar/n03467517_17233-3.png 4 +sketch/guitar/n03467517_17233-4.png 4 +sketch/guitar/n03467517_17233-5.png 4 +sketch/guitar/n03467517_19701-1.png 4 +sketch/guitar/n03467517_19701-2.png 4 +sketch/guitar/n03467517_19701-3.png 4 +sketch/guitar/n03467517_19701-4.png 4 +sketch/guitar/n03467517_19701-5.png 4 +sketch/guitar/n03467517_21782-1.png 4 +sketch/guitar/n03467517_21782-2.png 4 +sketch/guitar/n03467517_21782-3.png 4 +sketch/guitar/n03467517_21782-4.png 4 +sketch/guitar/n03467517_21782-5.png 4 +sketch/guitar/n03467517_21884-1.png 4 +sketch/guitar/n03467517_21884-2.png 4 +sketch/guitar/n03467517_21884-3.png 4 +sketch/guitar/n03467517_21884-4.png 4 +sketch/guitar/n03467517_21884-5.png 4 +sketch/guitar/n03467517_21884-6.png 4 +sketch/guitar/n03467517_22246-1.png 4 +sketch/guitar/n03467517_22246-2.png 4 +sketch/guitar/n03467517_22246-3.png 4 +sketch/guitar/n03467517_22246-4.png 4 +sketch/guitar/n03467517_22246-5.png 4 +sketch/guitar/n03467517_22246-6.png 4 +sketch/guitar/n03467517_22374-1.png 4 +sketch/guitar/n03467517_22374-2.png 4 +sketch/guitar/n03467517_22374-3.png 4 +sketch/guitar/n03467517_22374-4.png 4 +sketch/guitar/n03467517_22374-5.png 4 +sketch/guitar/n03467517_22785-1.png 4 +sketch/guitar/n03467517_22785-2.png 4 +sketch/guitar/n03467517_22785-3.png 4 +sketch/guitar/n03467517_22785-4.png 4 +sketch/guitar/n03467517_22785-5.png 4 +sketch/guitar/n03467517_22871-1.png 4 +sketch/guitar/n03467517_22871-2.png 4 +sketch/guitar/n03467517_22871-3.png 4 +sketch/guitar/n03467517_22871-4.png 4 +sketch/guitar/n03467517_22871-5.png 4 +sketch/guitar/n03467517_23229-1.png 4 +sketch/guitar/n03467517_23229-2.png 4 +sketch/guitar/n03467517_23229-3.png 4 +sketch/guitar/n03467517_23229-4.png 4 +sketch/guitar/n03467517_23229-5.png 4 +sketch/guitar/n03467517_24525-1.png 4 +sketch/guitar/n03467517_24525-2.png 4 +sketch/guitar/n03467517_24525-3.png 4 +sketch/guitar/n03467517_24525-4.png 4 +sketch/guitar/n03467517_24525-5.png 4 +sketch/guitar/n03467517_24525-6.png 4 +sketch/horse/n02374451_597-1.png 5 +sketch/horse/n02374451_597-2.png 5 +sketch/horse/n02374451_597-3.png 5 +sketch/horse/n02374451_597-4.png 5 +sketch/horse/n02374451_597-5.png 5 +sketch/horse/n02374451_597-6.png 5 +sketch/horse/n02374451_597-7.png 5 +sketch/horse/n02374451_777-1.png 5 +sketch/horse/n02374451_777-2.png 5 +sketch/horse/n02374451_777-3.png 5 +sketch/horse/n02374451_777-4.png 5 +sketch/horse/n02374451_777-5.png 5 +sketch/horse/n02374451_777-6.png 5 +sketch/horse/n02374451_779-1.png 5 +sketch/horse/n02374451_779-2.png 5 +sketch/horse/n02374451_779-3.png 5 +sketch/horse/n02374451_779-4.png 5 +sketch/horse/n02374451_779-5.png 5 +sketch/horse/n02374451_779-6.png 5 +sketch/horse/n02374451_779-7.png 5 +sketch/horse/n02374451_779-8.png 5 +sketch/horse/n02374451_779-9.png 5 +sketch/horse/n02374451_916-1.png 5 +sketch/horse/n02374451_916-2.png 5 +sketch/horse/n02374451_916-3.png 5 +sketch/horse/n02374451_916-4.png 5 +sketch/horse/n02374451_916-5.png 5 +sketch/horse/n02374451_916-6.png 5 +sketch/horse/n02374451_925-1.png 5 +sketch/horse/n02374451_925-2.png 5 +sketch/horse/n02374451_925-3.png 5 +sketch/horse/n02374451_925-4.png 5 +sketch/horse/n02374451_925-5.png 5 +sketch/horse/n02374451_925-6.png 5 +sketch/horse/n02374451_925-7.png 5 +sketch/horse/n02374451_929-1.png 5 +sketch/horse/n02374451_929-2.png 5 +sketch/horse/n02374451_929-3.png 5 +sketch/horse/n02374451_929-4.png 5 +sketch/horse/n02374451_929-5.png 5 +sketch/horse/n02374451_929-6.png 5 +sketch/horse/n02374451_1189-1.png 5 +sketch/horse/n02374451_1189-2.png 5 +sketch/horse/n02374451_1189-3.png 5 +sketch/horse/n02374451_1189-4.png 5 +sketch/horse/n02374451_1189-5.png 5 +sketch/horse/n02374451_1189-6.png 5 +sketch/horse/n02374451_1189-7.png 5 +sketch/horse/n02374451_1234-1.png 5 +sketch/horse/n02374451_1234-2.png 5 +sketch/horse/n02374451_1234-3.png 5 +sketch/horse/n02374451_1234-4.png 5 +sketch/horse/n02374451_1234-5.png 5 +sketch/horse/n02374451_1234-6.png 5 +sketch/horse/n02374451_1340-1.png 5 +sketch/horse/n02374451_1340-2.png 5 +sketch/horse/n02374451_1340-3.png 5 +sketch/horse/n02374451_1340-4.png 5 +sketch/horse/n02374451_1340-5.png 5 +sketch/horse/n02374451_1340-6.png 5 +sketch/horse/n02374451_1340-7.png 5 +sketch/horse/n02374451_1340-8.png 5 +sketch/horse/n02374451_1340-9.png 5 +sketch/horse/n02374451_1340-10.png 5 +sketch/horse/n02374451_1340-11.png 5 +sketch/horse/n02374451_1443-1.png 5 +sketch/horse/n02374451_1443-2.png 5 +sketch/horse/n02374451_1443-3.png 5 +sketch/horse/n02374451_1443-4.png 5 +sketch/horse/n02374451_1443-5.png 5 +sketch/horse/n02374451_1443-6.png 5 +sketch/horse/n02374451_1443-7.png 5 +sketch/horse/n02374451_1443-8.png 5 +sketch/horse/n02374451_1695-1.png 5 +sketch/horse/n02374451_1695-2.png 5 +sketch/horse/n02374451_1695-3.png 5 +sketch/horse/n02374451_1695-4.png 5 +sketch/horse/n02374451_1695-5.png 5 +sketch/horse/n02374451_1695-6.png 5 +sketch/horse/n02374451_1695-7.png 5 +sketch/horse/n02374451_2233-1.png 5 +sketch/horse/n02374451_2233-2.png 5 +sketch/horse/n02374451_2233-3.png 5 +sketch/horse/n02374451_2233-4.png 5 +sketch/horse/n02374451_2233-5.png 5 +sketch/horse/n02374451_2233-6.png 5 +sketch/horse/n02374451_2233-7.png 5 +sketch/horse/n02374451_2248-1.png 5 +sketch/horse/n02374451_2248-2.png 5 +sketch/horse/n02374451_2248-3.png 5 +sketch/horse/n02374451_2248-4.png 5 +sketch/horse/n02374451_2248-5.png 5 +sketch/horse/n02374451_2248-6.png 5 +sketch/horse/n02374451_2248-7.png 5 +sketch/horse/n02374451_2248-8.png 5 +sketch/horse/n02374451_2372-1.png 5 +sketch/horse/n02374451_2372-2.png 5 +sketch/horse/n02374451_2372-3.png 5 +sketch/horse/n02374451_2372-4.png 5 +sketch/horse/n02374451_2372-5.png 5 +sketch/horse/n02374451_2372-6.png 5 +sketch/horse/n02374451_2372-7.png 5 +sketch/horse/n02374451_2372-8.png 5 +sketch/horse/n02374451_2478-1.png 5 +sketch/horse/n02374451_2478-2.png 5 +sketch/horse/n02374451_2478-3.png 5 +sketch/horse/n02374451_2478-4.png 5 +sketch/horse/n02374451_2478-5.png 5 +sketch/horse/n02374451_2616-1.png 5 +sketch/horse/n02374451_2616-2.png 5 +sketch/horse/n02374451_2616-3.png 5 +sketch/horse/n02374451_2616-4.png 5 +sketch/horse/n02374451_2616-5.png 5 +sketch/horse/n02374451_2616-6.png 5 +sketch/horse/n02374451_2616-7.png 5 +sketch/horse/n02374451_2616-8.png 5 +sketch/horse/n02374451_2616-9.png 5 +sketch/horse/n02374451_2616-10.png 5 +sketch/horse/n02374451_2733-1.png 5 +sketch/horse/n02374451_2733-2.png 5 +sketch/horse/n02374451_2733-3.png 5 +sketch/horse/n02374451_2733-4.png 5 +sketch/horse/n02374451_2733-5.png 5 +sketch/horse/n02374451_2733-6.png 5 +sketch/horse/n02374451_2733-7.png 5 +sketch/horse/n02374451_2743-1.png 5 +sketch/horse/n02374451_2743-2.png 5 +sketch/horse/n02374451_2743-3.png 5 +sketch/horse/n02374451_2743-4.png 5 +sketch/horse/n02374451_2743-5.png 5 +sketch/horse/n02374451_2743-6.png 5 +sketch/horse/n02374451_2743-7.png 5 +sketch/horse/n02374451_2825-1.png 5 +sketch/horse/n02374451_2825-2.png 5 +sketch/horse/n02374451_2825-3.png 5 +sketch/horse/n02374451_2825-4.png 5 +sketch/horse/n02374451_2825-5.png 5 +sketch/horse/n02374451_2825-6.png 5 +sketch/horse/n02374451_2825-7.png 5 +sketch/horse/n02374451_2825-8.png 5 +sketch/horse/n02374451_2825-9.png 5 +sketch/horse/n02374451_2825-10.png 5 +sketch/horse/n02374451_2846-1.png 5 +sketch/horse/n02374451_2846-2.png 5 +sketch/horse/n02374451_2846-3.png 5 +sketch/horse/n02374451_2846-4.png 5 +sketch/horse/n02374451_2846-5.png 5 +sketch/horse/n02374451_2846-6.png 5 +sketch/horse/n02374451_2846-7.png 5 +sketch/horse/n02374451_2846-8.png 5 +sketch/horse/n02374451_2846-9.png 5 +sketch/horse/n02374451_3388-1.png 5 +sketch/horse/n02374451_3388-2.png 5 +sketch/horse/n02374451_3388-3.png 5 +sketch/horse/n02374451_3388-4.png 5 +sketch/horse/n02374451_3388-5.png 5 +sketch/horse/n02374451_3388-6.png 5 +sketch/horse/n02374451_3388-7.png 5 +sketch/horse/n02374451_3388-8.png 5 +sketch/horse/n02374451_3388-9.png 5 +sketch/horse/n02374451_3808-1.png 5 +sketch/horse/n02374451_3808-2.png 5 +sketch/horse/n02374451_3808-3.png 5 +sketch/horse/n02374451_3808-4.png 5 +sketch/horse/n02374451_3808-5.png 5 +sketch/horse/n02374451_3808-6.png 5 +sketch/horse/n02374451_3808-7.png 5 +sketch/horse/n02374451_3808-8.png 5 +sketch/horse/n02374451_3808-9.png 5 +sketch/horse/n02374451_4538-1.png 5 +sketch/horse/n02374451_4538-2.png 5 +sketch/horse/n02374451_4538-3.png 5 +sketch/horse/n02374451_4538-4.png 5 +sketch/horse/n02374451_4538-5.png 5 +sketch/horse/n02374451_4538-6.png 5 +sketch/horse/n02374451_4538-7.png 5 +sketch/horse/n02374451_4538-8.png 5 +sketch/horse/n02374451_4538-9.png 5 +sketch/horse/n02374451_4553-1.png 5 +sketch/horse/n02374451_4553-2.png 5 +sketch/horse/n02374451_4553-3.png 5 +sketch/horse/n02374451_4553-4.png 5 +sketch/horse/n02374451_4553-5.png 5 +sketch/horse/n02374451_4553-6.png 5 +sketch/horse/n02374451_4553-7.png 5 +sketch/horse/n02374451_4795-1.png 5 +sketch/horse/n02374451_4795-2.png 5 +sketch/horse/n02374451_4795-3.png 5 +sketch/horse/n02374451_4795-4.png 5 +sketch/horse/n02374451_4795-5.png 5 +sketch/horse/n02374451_4795-6.png 5 +sketch/horse/n02374451_4795-7.png 5 +sketch/horse/n02374451_4795-8.png 5 +sketch/horse/n02374451_4818-1.png 5 +sketch/horse/n02374451_4818-2.png 5 +sketch/horse/n02374451_4818-3.png 5 +sketch/horse/n02374451_4818-4.png 5 +sketch/horse/n02374451_4818-5.png 5 +sketch/horse/n02374451_4818-6.png 5 +sketch/horse/n02374451_4818-7.png 5 +sketch/horse/n02374451_4963-1.png 5 +sketch/horse/n02374451_4963-2.png 5 +sketch/horse/n02374451_4963-3.png 5 +sketch/horse/n02374451_4963-4.png 5 +sketch/horse/n02374451_4963-5.png 5 +sketch/horse/n02374451_4963-6.png 5 +sketch/horse/n02374451_5084-1.png 5 +sketch/horse/n02374451_5084-2.png 5 +sketch/horse/n02374451_5084-3.png 5 +sketch/horse/n02374451_5084-4.png 5 +sketch/horse/n02374451_5084-5.png 5 +sketch/horse/n02374451_5084-6.png 5 +sketch/horse/n02374451_6192-1.png 5 +sketch/horse/n02374451_6192-2.png 5 +sketch/horse/n02374451_6192-3.png 5 +sketch/horse/n02374451_6192-4.png 5 +sketch/horse/n02374451_6192-5.png 5 +sketch/horse/n02374451_6192-6.png 5 +sketch/horse/n02374451_6192-7.png 5 +sketch/horse/n02374451_6207-1.png 5 +sketch/horse/n02374451_6207-2.png 5 +sketch/horse/n02374451_6207-3.png 5 +sketch/horse/n02374451_6207-4.png 5 +sketch/horse/n02374451_6207-5.png 5 +sketch/horse/n02374451_6207-6.png 5 +sketch/horse/n02374451_7631-1.png 5 +sketch/horse/n02374451_7631-2.png 5 +sketch/horse/n02374451_7631-3.png 5 +sketch/horse/n02374451_7631-4.png 5 +sketch/horse/n02374451_7631-5.png 5 +sketch/horse/n02374451_7631-6.png 5 +sketch/horse/n02374451_7631-7.png 5 +sketch/horse/n02374451_8065-1.png 5 +sketch/horse/n02374451_8065-2.png 5 +sketch/horse/n02374451_8065-3.png 5 +sketch/horse/n02374451_8065-4.png 5 +sketch/horse/n02374451_8065-5.png 5 +sketch/horse/n02374451_8065-6.png 5 +sketch/horse/n02374451_8269-1.png 5 +sketch/horse/n02374451_8269-2.png 5 +sketch/horse/n02374451_8269-3.png 5 +sketch/horse/n02374451_8269-4.png 5 +sketch/horse/n02374451_8269-5.png 5 +sketch/horse/n02374451_8269-6.png 5 +sketch/horse/n02374451_8269-7.png 5 +sketch/horse/n02374451_8269-8.png 5 +sketch/horse/n02374451_8269-9.png 5 +sketch/horse/n02374451_8526-1.png 5 +sketch/horse/n02374451_8526-2.png 5 +sketch/horse/n02374451_8526-3.png 5 +sketch/horse/n02374451_8526-4.png 5 +sketch/horse/n02374451_8526-5.png 5 +sketch/horse/n02374451_8526-6.png 5 +sketch/horse/n02374451_8718-1.png 5 +sketch/horse/n02374451_8718-2.png 5 +sketch/horse/n02374451_8718-3.png 5 +sketch/horse/n02374451_8718-4.png 5 +sketch/horse/n02374451_8718-5.png 5 +sketch/horse/n02374451_8718-6.png 5 +sketch/horse/n02374451_8744-1.png 5 +sketch/horse/n02374451_8744-2.png 5 +sketch/horse/n02374451_8744-3.png 5 +sketch/horse/n02374451_8744-4.png 5 +sketch/horse/n02374451_8744-5.png 5 +sketch/horse/n02374451_8744-6.png 5 +sketch/horse/n02374451_8744-7.png 5 +sketch/horse/n02374451_8744-8.png 5 +sketch/horse/n02374451_8744-9.png 5 +sketch/horse/n02374451_8744-10.png 5 +sketch/horse/n02374451_8806-1.png 5 +sketch/horse/n02374451_8806-2.png 5 +sketch/horse/n02374451_8806-3.png 5 +sketch/horse/n02374451_8806-4.png 5 +sketch/horse/n02374451_8806-5.png 5 +sketch/horse/n02374451_8806-6.png 5 +sketch/horse/n02374451_8806-7.png 5 +sketch/horse/n02374451_8806-8.png 5 +sketch/horse/n02374451_9064-1.png 5 +sketch/horse/n02374451_9064-2.png 5 +sketch/horse/n02374451_9064-3.png 5 +sketch/horse/n02374451_9064-4.png 5 +sketch/horse/n02374451_9064-5.png 5 +sketch/horse/n02374451_9064-6.png 5 +sketch/horse/n02374451_9225-1.png 5 +sketch/horse/n02374451_9225-2.png 5 +sketch/horse/n02374451_9225-3.png 5 +sketch/horse/n02374451_9225-4.png 5 +sketch/horse/n02374451_9225-5.png 5 +sketch/horse/n02374451_9225-6.png 5 +sketch/horse/n02374451_9225-7.png 5 +sketch/horse/n02374451_9225-8.png 5 +sketch/horse/n02374451_9443-1.png 5 +sketch/horse/n02374451_9443-2.png 5 +sketch/horse/n02374451_9443-3.png 5 +sketch/horse/n02374451_9443-4.png 5 +sketch/horse/n02374451_9443-5.png 5 +sketch/horse/n02374451_9443-6.png 5 +sketch/horse/n02374451_9443-7.png 5 +sketch/horse/n02374451_9892-1.png 5 +sketch/horse/n02374451_9892-2.png 5 +sketch/horse/n02374451_9892-3.png 5 +sketch/horse/n02374451_9892-4.png 5 +sketch/horse/n02374451_9892-5.png 5 +sketch/horse/n02374451_9892-6.png 5 +sketch/horse/n02374451_9892-7.png 5 +sketch/horse/n02374451_10081-1.png 5 +sketch/horse/n02374451_10081-2.png 5 +sketch/horse/n02374451_10081-3.png 5 +sketch/horse/n02374451_10081-4.png 5 +sketch/horse/n02374451_10081-5.png 5 +sketch/horse/n02374451_10081-6.png 5 +sketch/horse/n02374451_10098-1.png 5 +sketch/horse/n02374451_10098-2.png 5 +sketch/horse/n02374451_10098-3.png 5 +sketch/horse/n02374451_10098-4.png 5 +sketch/horse/n02374451_10098-5.png 5 +sketch/horse/n02374451_10098-6.png 5 +sketch/horse/n02374451_10098-7.png 5 +sketch/horse/n02374451_10099-1.png 5 +sketch/horse/n02374451_10099-2.png 5 +sketch/horse/n02374451_10099-3.png 5 +sketch/horse/n02374451_10099-4.png 5 +sketch/horse/n02374451_10099-5.png 5 +sketch/horse/n02374451_10099-6.png 5 +sketch/horse/n02374451_10099-7.png 5 +sketch/horse/n02374451_10099-8.png 5 +sketch/horse/n02374451_10099-9.png 5 +sketch/horse/n02374451_10118-1.png 5 +sketch/horse/n02374451_10118-2.png 5 +sketch/horse/n02374451_10118-3.png 5 +sketch/horse/n02374451_10118-4.png 5 +sketch/horse/n02374451_10118-5.png 5 +sketch/horse/n02374451_10331-1.png 5 +sketch/horse/n02374451_10331-2.png 5 +sketch/horse/n02374451_10331-3.png 5 +sketch/horse/n02374451_10331-4.png 5 +sketch/horse/n02374451_10331-5.png 5 +sketch/horse/n02374451_10669-1.png 5 +sketch/horse/n02374451_10669-2.png 5 +sketch/horse/n02374451_10669-3.png 5 +sketch/horse/n02374451_10669-4.png 5 +sketch/horse/n02374451_10669-5.png 5 +sketch/horse/n02374451_10669-6.png 5 +sketch/horse/n02374451_10669-7.png 5 +sketch/horse/n02374451_10669-8.png 5 +sketch/horse/n02374451_10669-9.png 5 +sketch/horse/n02374451_10761-1.png 5 +sketch/horse/n02374451_10761-2.png 5 +sketch/horse/n02374451_10761-3.png 5 +sketch/horse/n02374451_10761-4.png 5 +sketch/horse/n02374451_10761-5.png 5 +sketch/horse/n02374451_10761-6.png 5 +sketch/horse/n02374451_10761-7.png 5 +sketch/horse/n02374451_10761-8.png 5 +sketch/horse/n02374451_10761-9.png 5 +sketch/horse/n02374451_10761-10.png 5 +sketch/horse/n02374451_10809-1.png 5 +sketch/horse/n02374451_10809-2.png 5 +sketch/horse/n02374451_10809-4.png 5 +sketch/horse/n02374451_10809-5.png 5 +sketch/horse/n02374451_10809-6.png 5 +sketch/horse/n02374451_10809-7.png 5 +sketch/horse/n02374451_10809-8.png 5 +sketch/horse/n02374451_11479-1.png 5 +sketch/horse/n02374451_11479-2.png 5 +sketch/horse/n02374451_11479-3.png 5 +sketch/horse/n02374451_11479-4.png 5 +sketch/horse/n02374451_11479-5.png 5 +sketch/horse/n02374451_11479-6.png 5 +sketch/horse/n02374451_11479-7.png 5 +sketch/horse/n02374451_11483-1.png 5 +sketch/horse/n02374451_11483-2.png 5 +sketch/horse/n02374451_11483-3.png 5 +sketch/horse/n02374451_11483-4.png 5 +sketch/horse/n02374451_11483-5.png 5 +sketch/horse/n02374451_11483-6.png 5 +sketch/horse/n02374451_11492-1.png 5 +sketch/horse/n02374451_11492-2.png 5 +sketch/horse/n02374451_11492-3.png 5 +sketch/horse/n02374451_11492-4.png 5 +sketch/horse/n02374451_11492-5.png 5 +sketch/horse/n02374451_11492-6.png 5 +sketch/horse/n02374451_11894-1.png 5 +sketch/horse/n02374451_11894-2.png 5 +sketch/horse/n02374451_11894-3.png 5 +sketch/horse/n02374451_11894-4.png 5 +sketch/horse/n02374451_11894-5.png 5 +sketch/horse/n02374451_11894-6.png 5 +sketch/horse/n02374451_11894-7.png 5 +sketch/horse/n02374451_11894-8.png 5 +sketch/horse/n02374451_11894-9.png 5 +sketch/horse/n02374451_12128-1.png 5 +sketch/horse/n02374451_12128-2.png 5 +sketch/horse/n02374451_12128-3.png 5 +sketch/horse/n02374451_12128-4.png 5 +sketch/horse/n02374451_12128-5.png 5 +sketch/horse/n02374451_12128-6.png 5 +sketch/horse/n02374451_12128-7.png 5 +sketch/horse/n02374451_12128-8.png 5 +sketch/horse/n02374451_12174-1.png 5 +sketch/horse/n02374451_12174-2.png 5 +sketch/horse/n02374451_12174-3.png 5 +sketch/horse/n02374451_12174-4.png 5 +sketch/horse/n02374451_12174-5.png 5 +sketch/horse/n02374451_12174-6.png 5 +sketch/horse/n02374451_12200-1.png 5 +sketch/horse/n02374451_12200-2.png 5 +sketch/horse/n02374451_12200-3.png 5 +sketch/horse/n02374451_12200-4.png 5 +sketch/horse/n02374451_12200-5.png 5 +sketch/horse/n02374451_12200-6.png 5 +sketch/horse/n02374451_12200-7.png 5 +sketch/horse/n02374451_12225-1.png 5 +sketch/horse/n02374451_12225-2.png 5 +sketch/horse/n02374451_12225-3.png 5 +sketch/horse/n02374451_12225-4.png 5 +sketch/horse/n02374451_12225-5.png 5 +sketch/horse/n02374451_12225-6.png 5 +sketch/horse/n02374451_12230-1.png 5 +sketch/horse/n02374451_12230-2.png 5 +sketch/horse/n02374451_12230-3.png 5 +sketch/horse/n02374451_12230-4.png 5 +sketch/horse/n02374451_12230-5.png 5 +sketch/horse/n02374451_12230-6.png 5 +sketch/horse/n02374451_12230-7.png 5 +sketch/horse/n02374451_12239-1.png 5 +sketch/horse/n02374451_12239-2.png 5 +sketch/horse/n02374451_12239-3.png 5 +sketch/horse/n02374451_12239-4.png 5 +sketch/horse/n02374451_12239-5.png 5 +sketch/horse/n02374451_12239-6.png 5 +sketch/horse/n02374451_12239-7.png 5 +sketch/horse/n02374451_12250-1.png 5 +sketch/horse/n02374451_12250-2.png 5 +sketch/horse/n02374451_12250-3.png 5 +sketch/horse/n02374451_12250-4.png 5 +sketch/horse/n02374451_12250-5.png 5 +sketch/horse/n02374451_12250-6.png 5 +sketch/horse/n02374451_12250-7.png 5 +sketch/horse/n02374451_12254-1.png 5 +sketch/horse/n02374451_12254-2.png 5 +sketch/horse/n02374451_12254-3.png 5 +sketch/horse/n02374451_12254-4.png 5 +sketch/horse/n02374451_12254-5.png 5 +sketch/horse/n02374451_12254-6.png 5 +sketch/horse/n02374451_12254-7.png 5 +sketch/horse/n02374451_12328-1.png 5 +sketch/horse/n02374451_12328-2.png 5 +sketch/horse/n02374451_12328-3.png 5 +sketch/horse/n02374451_12328-4.png 5 +sketch/horse/n02374451_12328-5.png 5 +sketch/horse/n02374451_12328-6.png 5 +sketch/horse/n02374451_12328-7.png 5 +sketch/horse/n02374451_12328-8.png 5 +sketch/horse/n02374451_12328-9.png 5 +sketch/horse/n02374451_12328-10.png 5 +sketch/horse/n02374451_12418-1.png 5 +sketch/horse/n02374451_12418-2.png 5 +sketch/horse/n02374451_12418-3.png 5 +sketch/horse/n02374451_12418-4.png 5 +sketch/horse/n02374451_12418-5.png 5 +sketch/horse/n02374451_12418-6.png 5 +sketch/horse/n02374451_12418-7.png 5 +sketch/horse/n02374451_12418-8.png 5 +sketch/horse/n02374451_12418-9.png 5 +sketch/horse/n02374451_12418-10.png 5 +sketch/horse/n02374451_12792-1.png 5 +sketch/horse/n02374451_12792-2.png 5 +sketch/horse/n02374451_12792-3.png 5 +sketch/horse/n02374451_12792-4.png 5 +sketch/horse/n02374451_12792-5.png 5 +sketch/horse/n02374451_12792-6.png 5 +sketch/horse/n02374451_12792-7.png 5 +sketch/horse/n02374451_12792-8.png 5 +sketch/horse/n02374451_12792-9.png 5 +sketch/horse/n02374451_12792-10.png 5 +sketch/horse/n02374451_12847-1.png 5 +sketch/horse/n02374451_12847-2.png 5 +sketch/horse/n02374451_12847-3.png 5 +sketch/horse/n02374451_12847-4.png 5 +sketch/horse/n02374451_12847-5.png 5 +sketch/horse/n02374451_12847-6.png 5 +sketch/horse/n02374451_12847-7.png 5 +sketch/horse/n02374451_12847-8.png 5 +sketch/horse/n02374451_13132-1.png 5 +sketch/horse/n02374451_13132-2.png 5 +sketch/horse/n02374451_13132-3.png 5 +sketch/horse/n02374451_13132-4.png 5 +sketch/horse/n02374451_13132-5.png 5 +sketch/horse/n02374451_13132-6.png 5 +sketch/horse/n02374451_13132-7.png 5 +sketch/horse/n02374451_13136-1.png 5 +sketch/horse/n02374451_13136-2.png 5 +sketch/horse/n02374451_13136-3.png 5 +sketch/horse/n02374451_13136-4.png 5 +sketch/horse/n02374451_13136-5.png 5 +sketch/horse/n02374451_13159-1.png 5 +sketch/horse/n02374451_13159-2.png 5 +sketch/horse/n02374451_13159-3.png 5 +sketch/horse/n02374451_13159-4.png 5 +sketch/horse/n02374451_13159-5.png 5 +sketch/horse/n02374451_13159-6.png 5 +sketch/horse/n02374451_13159-7.png 5 +sketch/horse/n02374451_13159-8.png 5 +sketch/horse/n02374451_13171-1.png 5 +sketch/horse/n02374451_13171-2.png 5 +sketch/horse/n02374451_13171-3.png 5 +sketch/horse/n02374451_13171-4.png 5 +sketch/horse/n02374451_13171-5.png 5 +sketch/horse/n02374451_13171-6.png 5 +sketch/horse/n02374451_13718-1.png 5 +sketch/horse/n02374451_13718-2.png 5 +sketch/horse/n02374451_13718-3.png 5 +sketch/horse/n02374451_13718-4.png 5 +sketch/horse/n02374451_13718-5.png 5 +sketch/horse/n02374451_13718-6.png 5 +sketch/horse/n02374451_14119-1.png 5 +sketch/horse/n02374451_14119-2.png 5 +sketch/horse/n02374451_14119-3.png 5 +sketch/horse/n02374451_14119-4.png 5 +sketch/horse/n02374451_14119-5.png 5 +sketch/horse/n02374451_14119-6.png 5 +sketch/horse/n02374451_14119-7.png 5 +sketch/horse/n02374451_14119-8.png 5 +sketch/horse/n02374451_14119-9.png 5 +sketch/horse/n02374451_14233-1.png 5 +sketch/horse/n02374451_14233-2.png 5 +sketch/horse/n02374451_14233-3.png 5 +sketch/horse/n02374451_14233-4.png 5 +sketch/horse/n02374451_14233-5.png 5 +sketch/horse/n02374451_14399-1.png 5 +sketch/horse/n02374451_14399-2.png 5 +sketch/horse/n02374451_14399-3.png 5 +sketch/horse/n02374451_14399-4.png 5 +sketch/horse/n02374451_14399-5.png 5 +sketch/horse/n02374451_14399-6.png 5 +sketch/horse/n02374451_14399-7.png 5 +sketch/horse/n02374451_14425-10.png 5 +sketch/horse/n02374451_14425-1.png 5 +sketch/horse/n02374451_14425-2.png 5 +sketch/horse/n02374451_14425-3.png 5 +sketch/horse/n02374451_14425-4.png 5 +sketch/horse/n02374451_14425-5.png 5 +sketch/horse/n02374451_14425-6.png 5 +sketch/horse/n02374451_14425-7.png 5 +sketch/horse/n02374451_14425-8.png 5 +sketch/horse/n02374451_14425-9.png 5 +sketch/horse/n02374451_14738-1.png 5 +sketch/horse/n02374451_14738-2.png 5 +sketch/horse/n02374451_14738-3.png 5 +sketch/horse/n02374451_14738-4.png 5 +sketch/horse/n02374451_14738-5.png 5 +sketch/horse/n02374451_14738-6.png 5 +sketch/horse/n02374451_14738-7.png 5 +sketch/horse/n02374451_14846-1.png 5 +sketch/horse/n02374451_14846-2.png 5 +sketch/horse/n02374451_14846-3.png 5 +sketch/horse/n02374451_14846-4.png 5 +sketch/horse/n02374451_14846-5.png 5 +sketch/horse/n02374451_14846-6.png 5 +sketch/horse/n02374451_14846-7.png 5 +sketch/horse/n02374451_15307-1.png 5 +sketch/horse/n02374451_15307-2.png 5 +sketch/horse/n02374451_15307-3.png 5 +sketch/horse/n02374451_15307-4.png 5 +sketch/horse/n02374451_15307-5.png 5 +sketch/horse/n02374451_15307-6.png 5 +sketch/horse/n02374451_15440-1.png 5 +sketch/horse/n02374451_15440-2.png 5 +sketch/horse/n02374451_15440-3.png 5 +sketch/horse/n02374451_15440-4.png 5 +sketch/horse/n02374451_15440-5.png 5 +sketch/horse/n02374451_15440-6.png 5 +sketch/horse/n02374451_15453-1.png 5 +sketch/horse/n02374451_15453-2.png 5 +sketch/horse/n02374451_15453-3.png 5 +sketch/horse/n02374451_15453-4.png 5 +sketch/horse/n02374451_15453-5.png 5 +sketch/horse/n02374451_15453-6.png 5 +sketch/horse/n02374451_15453-7.png 5 +sketch/horse/n02374451_15669-1.png 5 +sketch/horse/n02374451_15669-2.png 5 +sketch/horse/n02374451_15669-3.png 5 +sketch/horse/n02374451_15669-4.png 5 +sketch/horse/n02374451_15669-5.png 5 +sketch/horse/n02374451_15669-6.png 5 +sketch/horse/n02374451_16194-1.png 5 +sketch/horse/n02374451_16194-2.png 5 +sketch/horse/n02374451_16194-3.png 5 +sketch/horse/n02374451_16194-4.png 5 +sketch/horse/n02374451_16194-5.png 5 +sketch/horse/n02374451_16194-6.png 5 +sketch/horse/n02374451_16358-1.png 5 +sketch/horse/n02374451_16358-2.png 5 +sketch/horse/n02374451_16358-3.png 5 +sketch/horse/n02374451_16358-4.png 5 +sketch/horse/n02374451_16358-5.png 5 +sketch/horse/n02374451_16358-6.png 5 +sketch/horse/n02374451_16948-1.png 5 +sketch/horse/n02374451_16948-2.png 5 +sketch/horse/n02374451_16948-3.png 5 +sketch/horse/n02374451_16948-4.png 5 +sketch/horse/n02374451_16948-5.png 5 +sketch/horse/n02374451_16948-6.png 5 +sketch/horse/n02374451_16948-7.png 5 +sketch/horse/n02374451_16948-8.png 5 +sketch/horse/n02374451_16948-9.png 5 +sketch/horse/n02374451_17043-1.png 5 +sketch/horse/n02374451_17043-2.png 5 +sketch/horse/n02374451_17043-3.png 5 +sketch/horse/n02374451_17043-4.png 5 +sketch/horse/n02374451_17043-5.png 5 +sketch/horse/n02374451_17043-6.png 5 +sketch/horse/n02374451_17384-1.png 5 +sketch/horse/n02374451_17384-2.png 5 +sketch/horse/n02374451_17384-3.png 5 +sketch/horse/n02374451_17384-4.png 5 +sketch/horse/n02374451_17384-5.png 5 +sketch/horse/n02374451_17384-6.png 5 +sketch/horse/n02374451_17384-7.png 5 +sketch/horse/n02374451_17384-8.png 5 +sketch/horse/n02374451_17474-1.png 5 +sketch/horse/n02374451_17474-2.png 5 +sketch/horse/n02374451_17474-3.png 5 +sketch/horse/n02374451_17474-4.png 5 +sketch/horse/n02374451_17474-5.png 5 +sketch/horse/n02374451_17474-6.png 5 +sketch/horse/n02374451_17474-7.png 5 +sketch/horse/n02374451_17474-8.png 5 +sketch/horse/n02374451_17634-1.png 5 +sketch/horse/n02374451_17634-2.png 5 +sketch/horse/n02374451_17634-3.png 5 +sketch/horse/n02374451_17634-4.png 5 +sketch/horse/n02374451_17634-5.png 5 +sketch/horse/n02374451_17634-6.png 5 +sketch/horse/n02374451_18192-1.png 5 +sketch/horse/n02374451_18192-2.png 5 +sketch/horse/n02374451_18192-3.png 5 +sketch/horse/n02374451_18192-4.png 5 +sketch/horse/n02374451_18192-5.png 5 +sketch/horse/n02374451_18192-6.png 5 +sketch/horse/n02374451_18570-1.png 5 +sketch/horse/n02374451_18570-2.png 5 +sketch/horse/n02374451_18570-3.png 5 +sketch/horse/n02374451_18570-4.png 5 +sketch/horse/n02374451_18570-5.png 5 +sketch/horse/n02374451_18570-6.png 5 +sketch/horse/n02374451_18570-7.png 5 +sketch/horse/n02374451_18909-1.png 5 +sketch/horse/n02374451_18909-2.png 5 +sketch/horse/n02374451_18909-3.png 5 +sketch/horse/n02374451_18909-4.png 5 +sketch/horse/n02374451_18909-5.png 5 +sketch/horse/n02374451_18909-6.png 5 +sketch/horse/8481.png 5 +sketch/horse/8482.png 5 +sketch/horse/8483.png 5 +sketch/horse/8484.png 5 +sketch/horse/8485.png 5 +sketch/horse/8486.png 5 +sketch/horse/8487.png 5 +sketch/horse/8488.png 5 +sketch/horse/8489.png 5 +sketch/horse/8490.png 5 +sketch/horse/8491.png 5 +sketch/horse/8492.png 5 +sketch/horse/8493.png 5 +sketch/horse/8494.png 5 +sketch/horse/8495.png 5 +sketch/horse/8496.png 5 +sketch/horse/8497.png 5 +sketch/horse/8498.png 5 +sketch/horse/8499.png 5 +sketch/horse/8500.png 5 +sketch/horse/8501.png 5 +sketch/horse/8502.png 5 +sketch/horse/8503.png 5 +sketch/horse/8504.png 5 +sketch/horse/8505.png 5 +sketch/horse/8506.png 5 +sketch/horse/8507.png 5 +sketch/horse/8508.png 5 +sketch/horse/8509.png 5 +sketch/horse/8510.png 5 +sketch/horse/8511.png 5 +sketch/horse/8512.png 5 +sketch/horse/8513.png 5 +sketch/horse/8514.png 5 +sketch/horse/8515.png 5 +sketch/horse/8516.png 5 +sketch/horse/8517.png 5 +sketch/horse/8518.png 5 +sketch/horse/8519.png 5 +sketch/horse/8520.png 5 +sketch/horse/8521.png 5 +sketch/horse/8522.png 5 +sketch/horse/8523.png 5 +sketch/horse/8524.png 5 +sketch/horse/8525.png 5 +sketch/horse/8526.png 5 +sketch/horse/8527.png 5 +sketch/horse/8528.png 5 +sketch/horse/8529.png 5 +sketch/horse/8530.png 5 +sketch/horse/8531.png 5 +sketch/horse/8532.png 5 +sketch/horse/8533.png 5 +sketch/horse/8534.png 5 +sketch/horse/8535.png 5 +sketch/horse/8536.png 5 +sketch/horse/8537.png 5 +sketch/horse/8538.png 5 +sketch/horse/8539.png 5 +sketch/horse/8540.png 5 +sketch/horse/8541.png 5 +sketch/horse/8542.png 5 +sketch/horse/8543.png 5 +sketch/horse/8544.png 5 +sketch/horse/8545.png 5 +sketch/horse/8546.png 5 +sketch/horse/8547.png 5 +sketch/horse/8548.png 5 +sketch/horse/8549.png 5 +sketch/horse/8550.png 5 +sketch/horse/8551.png 5 +sketch/horse/8552.png 5 +sketch/horse/8553.png 5 +sketch/horse/8554.png 5 +sketch/horse/8555.png 5 +sketch/horse/8556.png 5 +sketch/horse/8557.png 5 +sketch/horse/8558.png 5 +sketch/horse/8559.png 5 +sketch/horse/8560.png 5 +sketch/house/8810.png 6 +sketch/house/8811.png 6 +sketch/house/8812.png 6 +sketch/house/8813.png 6 +sketch/house/8814.png 6 +sketch/house/8815.png 6 +sketch/house/8816.png 6 +sketch/house/8817.png 6 +sketch/house/8818.png 6 +sketch/house/8819.png 6 +sketch/house/8820.png 6 +sketch/house/8821.png 6 +sketch/house/8822.png 6 +sketch/house/8823.png 6 +sketch/house/8824.png 6 +sketch/house/8825.png 6 +sketch/house/8826.png 6 +sketch/house/8827.png 6 +sketch/house/8828.png 6 +sketch/house/8829.png 6 +sketch/house/8830.png 6 +sketch/house/8831.png 6 +sketch/house/8832.png 6 +sketch/house/8833.png 6 +sketch/house/8834.png 6 +sketch/house/8835.png 6 +sketch/house/8836.png 6 +sketch/house/8837.png 6 +sketch/house/8838.png 6 +sketch/house/8839.png 6 +sketch/house/8840.png 6 +sketch/house/8841.png 6 +sketch/house/8842.png 6 +sketch/house/8843.png 6 +sketch/house/8844.png 6 +sketch/house/8845.png 6 +sketch/house/8846.png 6 +sketch/house/8847.png 6 +sketch/house/8848.png 6 +sketch/house/8849.png 6 +sketch/house/8850.png 6 +sketch/house/8851.png 6 +sketch/house/8852.png 6 +sketch/house/8853.png 6 +sketch/house/8854.png 6 +sketch/house/8855.png 6 +sketch/house/8856.png 6 +sketch/house/8857.png 6 +sketch/house/8858.png 6 +sketch/house/8859.png 6 +sketch/house/8860.png 6 +sketch/house/8861.png 6 +sketch/house/8862.png 6 +sketch/house/8863.png 6 +sketch/house/8864.png 6 +sketch/house/8865.png 6 +sketch/house/8866.png 6 +sketch/house/8867.png 6 +sketch/house/8868.png 6 +sketch/house/8869.png 6 +sketch/house/8870.png 6 +sketch/house/8871.png 6 +sketch/house/8872.png 6 +sketch/house/8873.png 6 +sketch/house/8874.png 6 +sketch/house/8875.png 6 +sketch/house/8876.png 6 +sketch/house/8877.png 6 +sketch/house/8878.png 6 +sketch/house/8879.png 6 +sketch/house/8880.png 6 +sketch/person/12098.png 7 +sketch/person/12099.png 7 +sketch/person/12100.png 7 +sketch/person/12101.png 7 +sketch/person/12102.png 7 +sketch/person/12103.png 7 +sketch/person/12104.png 7 +sketch/person/12105.png 7 +sketch/person/12106.png 7 +sketch/person/12107.png 7 +sketch/person/12108.png 7 +sketch/person/12109.png 7 +sketch/person/12110.png 7 +sketch/person/12111.png 7 +sketch/person/12112.png 7 +sketch/person/12113.png 7 +sketch/person/12114.png 7 +sketch/person/12115.png 7 +sketch/person/12116.png 7 +sketch/person/12117.png 7 +sketch/person/12118.png 7 +sketch/person/12119.png 7 +sketch/person/12120.png 7 +sketch/person/12121.png 7 +sketch/person/12122.png 7 +sketch/person/12123.png 7 +sketch/person/12124.png 7 +sketch/person/12125.png 7 +sketch/person/12126.png 7 +sketch/person/12127.png 7 +sketch/person/12128.png 7 +sketch/person/12129.png 7 +sketch/person/12130.png 7 +sketch/person/12131.png 7 +sketch/person/12132.png 7 +sketch/person/12133.png 7 +sketch/person/12134.png 7 +sketch/person/12135.png 7 +sketch/person/12136.png 7 +sketch/person/12137.png 7 +sketch/person/12138.png 7 +sketch/person/12139.png 7 +sketch/person/12140.png 7 +sketch/person/12141.png 7 +sketch/person/12142.png 7 +sketch/person/12143.png 7 +sketch/person/12144.png 7 +sketch/person/12145.png 7 +sketch/person/12146.png 7 +sketch/person/12147.png 7 +sketch/person/12148.png 7 +sketch/person/12149.png 7 +sketch/person/12150.png 7 +sketch/person/12151.png 7 +sketch/person/12152.png 7 +sketch/person/12153.png 7 +sketch/person/12154.png 7 +sketch/person/12155.png 7 +sketch/person/12156.png 7 +sketch/person/12157.png 7 +sketch/person/12158.png 7 +sketch/person/12159.png 7 +sketch/person/12160.png 7 +sketch/person/12161.png 7 +sketch/person/12162.png 7 +sketch/person/12163.png 7 +sketch/person/12164.png 7 +sketch/person/12165.png 7 +sketch/person/12166.png 7 +sketch/person/12167.png 7 +sketch/person/12168.png 7 +sketch/person/12169.png 7 +sketch/person/12170.png 7 +sketch/person/12171.png 7 +sketch/person/12172.png 7 +sketch/person/12173.png 7 +sketch/person/12174.png 7 +sketch/person/12175.png 7 +sketch/person/12176.png 7 +sketch/person/12177.png 7 +sketch/person/12178.png 7 +sketch/person/12179.png 7 +sketch/person/12180.png 7 +sketch/person/12181.png 7 +sketch/person/12182.png 7 +sketch/person/12183.png 7 +sketch/person/12184.png 7 +sketch/person/12185.png 7 +sketch/person/12186.png 7 +sketch/person/12187.png 7 +sketch/person/12188.png 7 +sketch/person/12189.png 7 +sketch/person/12190.png 7 +sketch/person/12191.png 7 +sketch/person/12192.png 7 +sketch/person/12193.png 7 +sketch/person/12194.png 7 +sketch/person/12195.png 7 +sketch/person/12196.png 7 +sketch/person/12197.png 7 +sketch/person/12198.png 7 +sketch/person/12199.png 7 +sketch/person/12200.png 7 +sketch/person/12201.png 7 +sketch/person/12202.png 7 +sketch/person/12203.png 7 +sketch/person/12204.png 7 +sketch/person/12205.png 7 +sketch/person/12206.png 7 +sketch/person/12207.png 7 +sketch/person/12208.png 7 +sketch/person/12209.png 7 +sketch/person/12210.png 7 +sketch/person/12211.png 7 +sketch/person/12212.png 7 +sketch/person/12213.png 7 +sketch/person/12214.png 7 +sketch/person/12215.png 7 +sketch/person/12216.png 7 +sketch/person/12217.png 7 +sketch/person/12218.png 7 +sketch/person/12219.png 7 +sketch/person/12220.png 7 +sketch/person/12221.png 7 +sketch/person/12222.png 7 +sketch/person/12223.png 7 +sketch/person/12224.png 7 +sketch/person/12225.png 7 +sketch/person/12226.png 7 +sketch/person/12227.png 7 +sketch/person/12228.png 7 +sketch/person/12229.png 7 +sketch/person/12230.png 7 +sketch/person/12231.png 7 +sketch/person/12232.png 7 +sketch/person/12233.png 7 +sketch/person/12234.png 7 +sketch/person/12235.png 7 +sketch/person/12236.png 7 +sketch/person/12237.png 7 +sketch/person/12238.png 7 +sketch/person/12239.png 7 +sketch/person/12240.png 7 diff --git a/domainlab/zdata/patches_permutation4jigsaw/permutations_100.npy b/domainlab/zdata/patches_permutation4jigsaw/permutations_100.npy new file mode 100644 index 000000000..e97dac647 Binary files /dev/null and b/domainlab/zdata/patches_permutation4jigsaw/permutations_100.npy differ diff --git a/domainlab/zdata/patches_permutation4jigsaw/permutations_30.npy b/domainlab/zdata/patches_permutation4jigsaw/permutations_30.npy new file mode 100644 index 000000000..d9e4fd8b3 Binary files /dev/null and b/domainlab/zdata/patches_permutation4jigsaw/permutations_30.npy differ diff --git a/domainlab/zdata/patches_permutation4jigsaw/permutations_31.npy b/domainlab/zdata/patches_permutation4jigsaw/permutations_31.npy new file mode 100644 index 000000000..196351ca0 Binary files /dev/null and b/domainlab/zdata/patches_permutation4jigsaw/permutations_31.npy differ diff --git a/domainlab/zdata/script/download_pacs.py b/domainlab/zdata/script/download_pacs.py new file mode 100644 index 000000000..51c346f24 --- /dev/null +++ b/domainlab/zdata/script/download_pacs.py @@ -0,0 +1,64 @@ +"this script can be used to download the pacs dataset" +import os +import tarfile +from zipfile import ZipFile + +import gdown + + +def stage_path(data_dir, name): + """ + creates the path to data_dir/name + if it does not exist already + """ + full_path = os.path.join(data_dir, name) + + if not os.path.exists(full_path): + os.makedirs(full_path) + + return full_path + + +def download_and_extract(url, dst, remove=True): + """ + downloads and extracts the data behind the url + and saves it at dst + """ + gdown.download(url, dst, quiet=False) + + if dst.endswith(".tar.gz"): + with open(dst, "r:gz") as tar: + tar.extractall(os.path.dirname(dst)) + tar.close() + + if dst.endswith(".tar"): + with open(dst, "r:") as tar: + tar.extractall(os.path.dirname(dst)) + tar.close() + + if dst.endswith(".zip"): + zfile = ZipFile(dst, "r") + zfile.extractall(os.path.dirname(dst)) + zfile.close() + + if remove: + os.remove(dst) + + +def download_pacs(data_dir): + """ + download and extract dataset pacs. + Dataset is saved at location data_dir + """ + full_path = stage_path(data_dir, "PACS") + + download_and_extract( + "https://drive.google.com/uc?id=1JFr8f805nMUelQWWmfnJR3y4_SYoN5Pd", + os.path.join(data_dir, "PACS.zip"), + ) + + os.rename(os.path.join(data_dir, "kfold"), full_path) + + +if __name__ == "__main__": + download_pacs("../pacs") diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_150.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_150.jpg new file mode 100644 index 000000000..8d01af8c3 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_150.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_151.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_151.jpg new file mode 100644 index 000000000..4d1bdc631 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_151.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_152.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_152.jpg new file mode 100644 index 000000000..6eb2ed77e Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_152.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_153.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_153.jpg new file mode 100644 index 000000000..7f95895b3 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_153.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_154.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_154.jpg new file mode 100644 index 000000000..038f7c75a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_154.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_155.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_155.jpg new file mode 100644 index 000000000..4cd7cb961 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_155.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_156.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_156.jpg new file mode 100644 index 000000000..417ff9fec Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_156.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_157.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_157.jpg new file mode 100644 index 000000000..f0bea00eb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_157.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_158.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_158.jpg new file mode 100644 index 000000000..ddcd649c7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_158.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_159.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_159.jpg new file mode 100644 index 000000000..b3cf78f0b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_159.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_160.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_160.jpg new file mode 100644 index 000000000..0f2b8a128 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_160.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_161.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_161.jpg new file mode 100644 index 000000000..33ac685cb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_161.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_162.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_162.jpg new file mode 100644 index 000000000..20267f3ff Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_162.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_163.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_163.jpg new file mode 100644 index 000000000..bae5f75fa Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_163.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_164.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_164.jpg new file mode 100644 index 000000000..93cbbf2a3 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_164.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_165.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_165.jpg new file mode 100644 index 000000000..4f8486a13 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_165.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_166.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_166.jpg new file mode 100644 index 000000000..e7bf34f79 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_166.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_167.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_167.jpg new file mode 100644 index 000000000..e4b17e52a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_167.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_168.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_168.jpg new file mode 100644 index 000000000..5d98cd4ab Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_168.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_169.jpg b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_169.jpg new file mode 100644 index 000000000..2efa536e5 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/auto/train_imgs_169.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_302.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_302.jpg new file mode 100644 index 000000000..7e79bb60a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_302.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_303.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_303.jpg new file mode 100644 index 000000000..b019ca0da Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_303.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_304.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_304.jpg new file mode 100644 index 000000000..a547a4342 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_304.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_305.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_305.jpg new file mode 100644 index 000000000..35d453852 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_305.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_306.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_306.jpg new file mode 100644 index 000000000..bad4d877f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_306.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_307.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_307.jpg new file mode 100644 index 000000000..fc3963301 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_307.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_308.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_308.jpg new file mode 100644 index 000000000..7327fa407 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_308.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_309.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_309.jpg new file mode 100644 index 000000000..c3e8789f3 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_309.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_310.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_310.jpg new file mode 100644 index 000000000..378c083b1 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_310.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_311.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_311.jpg new file mode 100644 index 000000000..c34e04832 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_311.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_312.jpg b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_312.jpg new file mode 100644 index 000000000..7ef8a0fcd Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/hund/train_imgs_312.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_344.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_344.jpg new file mode 100644 index 000000000..ad487291a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_344.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_345.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_345.jpg new file mode 100644 index 000000000..0554d6542 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_345.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_346.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_346.jpg new file mode 100644 index 000000000..97b441cce Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_346.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_347.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_347.jpg new file mode 100644 index 000000000..7f93da2aa Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_347.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_348.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_348.jpg new file mode 100644 index 000000000..77ac55168 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_348.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_349.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_349.jpg new file mode 100644 index 000000000..557945edd Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_349.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_350.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_350.jpg new file mode 100644 index 000000000..65fab7eb1 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_350.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_351.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_351.jpg new file mode 100644 index 000000000..9afc1b7c7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_351.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_352.jpg b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_352.jpg new file mode 100644 index 000000000..c1a367b04 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/mensch/train_imgs_352.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_227.jpg b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_227.jpg new file mode 100644 index 000000000..b8e68d5f6 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_227.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_228.jpg b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_228.jpg new file mode 100644 index 000000000..4d685f58d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_228.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_229.jpg b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_229.jpg new file mode 100644 index 000000000..54f87677d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_229.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_230.jpg b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_230.jpg new file mode 100644 index 000000000..2cce711ab Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_230.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_231.jpg b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_231.jpg new file mode 100644 index 000000000..6e2036865 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_231.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_232.jpg b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_232.jpg new file mode 100644 index 000000000..d2878a44b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/stuhl/train_imgs_232.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_1.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_1.jpg new file mode 100644 index 000000000..36e8af5d6 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_1.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_2.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_2.jpg new file mode 100644 index 000000000..5affad9fb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_2.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_3.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_3.jpg new file mode 100644 index 000000000..b85bdc572 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_3.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_4.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_4.jpg new file mode 100644 index 000000000..df57a475a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_4.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_5.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_5.jpg new file mode 100644 index 000000000..d5c1394c5 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_5.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_6.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_6.jpg new file mode 100644 index 000000000..aac9ff7a9 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_6.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_7.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_7.jpg new file mode 100644 index 000000000..3778a5f82 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_7.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_8.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_8.jpg new file mode 100644 index 000000000..e77fd8b77 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_8.jpg differ diff --git a/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_9.jpg b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_9.jpg new file mode 100644 index 000000000..45d4fce7b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/caltech/vogel/train_imgs_9.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_1.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_1.jpg new file mode 100644 index 000000000..fa62a47f9 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_1.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_10.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_10.jpg new file mode 100644 index 000000000..b690f5c0f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_10.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_11.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_11.jpg new file mode 100644 index 000000000..fc9eacc24 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_11.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_12.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_12.jpg new file mode 100644 index 000000000..4717327ea Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_12.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_13.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_13.jpg new file mode 100644 index 000000000..1e749728c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_13.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_14.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_14.jpg new file mode 100644 index 000000000..d7ab9c7d2 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_14.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_15.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_15.jpg new file mode 100644 index 000000000..6bdaa4adf Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_15.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_16.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_16.jpg new file mode 100644 index 000000000..3c8a0bbcf Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_16.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_17.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_17.jpg new file mode 100644 index 000000000..245636d68 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_17.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_18.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_18.jpg new file mode 100644 index 000000000..ce4516875 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_18.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_19.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_19.jpg new file mode 100644 index 000000000..5243db38c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_19.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_2.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_2.jpg new file mode 100644 index 000000000..adb944495 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_2.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_20.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_20.jpg new file mode 100644 index 000000000..9d2a94afb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_20.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_21.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_21.jpg new file mode 100644 index 000000000..8b2fd0903 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_21.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_22.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_22.jpg new file mode 100644 index 000000000..210ef5efb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_22.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_23.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_23.jpg new file mode 100644 index 000000000..5e47e9363 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_23.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_24.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_24.jpg new file mode 100644 index 000000000..d2e6cd15f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_24.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_25.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_25.jpg new file mode 100644 index 000000000..925013222 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_25.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_26.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_26.jpg new file mode 100644 index 000000000..c19911e9d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_26.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_27.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_27.jpg new file mode 100644 index 000000000..dfc58dc55 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_27.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_28.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_28.jpg new file mode 100644 index 000000000..d7f5a3c20 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_28.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_29.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_29.jpg new file mode 100644 index 000000000..bbc4bbec8 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_29.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_3.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_3.jpg new file mode 100644 index 000000000..1fdc623ba Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_3.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_30.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_30.jpg new file mode 100644 index 000000000..b48f0df0f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_30.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_31.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_31.jpg new file mode 100644 index 000000000..2d7448309 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_31.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_32.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_32.jpg new file mode 100644 index 000000000..03fa4f818 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_32.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_33.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_33.jpg new file mode 100644 index 000000000..9dc6bcc6c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_33.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_34.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_34.jpg new file mode 100644 index 000000000..2879c5e0c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_34.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_35.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_35.jpg new file mode 100644 index 000000000..7a16d6f34 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_35.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_36.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_36.jpg new file mode 100644 index 000000000..6104ff96e Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_36.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_37.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_37.jpg new file mode 100644 index 000000000..6ce48a9d9 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_37.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_38.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_38.jpg new file mode 100644 index 000000000..2a1366fca Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_38.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_39.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_39.jpg new file mode 100644 index 000000000..76d101104 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_39.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_4.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_4.jpg new file mode 100644 index 000000000..4e970302b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_4.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_40.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_40.jpg new file mode 100644 index 000000000..1b4544988 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_40.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_41.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_41.jpg new file mode 100644 index 000000000..58ac89b3d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_41.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_42.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_42.jpg new file mode 100644 index 000000000..1788966d7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_42.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_43.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_43.jpg new file mode 100644 index 000000000..bfdc2c869 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_43.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_44.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_44.jpg new file mode 100644 index 000000000..37b476a41 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_44.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_45.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_45.jpg new file mode 100644 index 000000000..7efb92de8 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_45.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_46.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_46.jpg new file mode 100644 index 000000000..e590b1c5e Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_46.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_47.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_47.jpg new file mode 100644 index 000000000..3cdbdeb6b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_47.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_48.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_48.jpg new file mode 100644 index 000000000..6c271309c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_48.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_49.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_49.jpg new file mode 100644 index 000000000..4030a021a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_49.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_5.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_5.jpg new file mode 100644 index 000000000..a5d6091d5 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_5.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_50.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_50.jpg new file mode 100644 index 000000000..d692b4a41 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_50.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_6.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_6.jpg new file mode 100644 index 000000000..4277e39f2 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_6.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_7.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_7.jpg new file mode 100644 index 000000000..d4daa9e87 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_7.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_8.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_8.jpg new file mode 100644 index 000000000..c23218241 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_8.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_9.jpg b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_9.jpg new file mode 100644 index 000000000..4ce7ba627 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/bird/train_imgs_9.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_51.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_51.jpg new file mode 100644 index 000000000..5a550fd87 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_51.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_52.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_52.jpg new file mode 100644 index 000000000..97f638ace Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_52.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_54.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_54.jpg new file mode 100644 index 000000000..fab8731c6 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_54.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_55.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_55.jpg new file mode 100644 index 000000000..3394d839f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_55.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_56.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_56.jpg new file mode 100644 index 000000000..4435ee7b4 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_56.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_57.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_57.jpg new file mode 100644 index 000000000..13daa967d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_57.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_58.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_58.jpg new file mode 100644 index 000000000..e49e1c825 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_58.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_59.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_59.jpg new file mode 100644 index 000000000..23f581a14 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_59.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_60.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_60.jpg new file mode 100644 index 000000000..85a28391d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_60.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_61.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_61.jpg new file mode 100644 index 000000000..33bc22be7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_61.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_64.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_64.jpg new file mode 100644 index 000000000..d31546a13 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_64.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_65.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_65.jpg new file mode 100644 index 000000000..7e3a9b223 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_65.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_69.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_69.jpg new file mode 100644 index 000000000..dff71951f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_69.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_70.jpg b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_70.jpg new file mode 100644 index 000000000..5a3d9d962 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/drive/train_imgs_70.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_870.jpg b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_870.jpg new file mode 100644 index 000000000..07687dfaa Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_870.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_871.jpg b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_871.jpg new file mode 100644 index 000000000..207ddfd52 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_871.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_880.jpg b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_880.jpg new file mode 100644 index 000000000..884441f5c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_880.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_883.jpg b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_883.jpg new file mode 100644 index 000000000..b77e4087f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_883.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_886.jpg b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_886.jpg new file mode 100644 index 000000000..d134a134c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_886.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_891.jpg b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_891.jpg new file mode 100644 index 000000000..8e5b6e5fc Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/husky/train_imgs_891.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_818.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_818.jpg new file mode 100644 index 000000000..1445f43ac Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_818.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_824.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_824.jpg new file mode 100644 index 000000000..b03925923 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_824.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_830.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_830.jpg new file mode 100644 index 000000000..3de4d6269 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_830.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_836.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_836.jpg new file mode 100644 index 000000000..0953fd6cf Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_836.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_837.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_837.jpg new file mode 100644 index 000000000..b408dc35c Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_837.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_849.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_849.jpg new file mode 100644 index 000000000..67d5c5abe Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_849.jpg differ diff --git a/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_858.jpg b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_858.jpg new file mode 100644 index 000000000..3789d7fdb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/labelme/sit/train_imgs_858.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1253.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1253.jpg new file mode 100644 index 000000000..00f561eb8 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1253.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1254.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1254.jpg new file mode 100644 index 000000000..aa2b1ef79 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1254.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1255.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1255.jpg new file mode 100644 index 000000000..aa74d706a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1255.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1256.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1256.jpg new file mode 100644 index 000000000..2ba1a73ca Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1256.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1257.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1257.jpg new file mode 100644 index 000000000..52bf5feda Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1257.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1258.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1258.jpg new file mode 100644 index 000000000..814095c57 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1258.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1259.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1259.jpg new file mode 100644 index 000000000..787bdb0e1 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1259.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1260.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1260.jpg new file mode 100644 index 000000000..43789d870 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1260.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1261.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1261.jpg new file mode 100644 index 000000000..8aad332e6 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1261.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1262.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1262.jpg new file mode 100644 index 000000000..8aa83944d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1262.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1263.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1263.jpg new file mode 100644 index 000000000..0aff5ec9f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1263.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1264.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1264.jpg new file mode 100644 index 000000000..73b79a98d Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1264.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1265.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1265.jpg new file mode 100644 index 000000000..301449719 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1265.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1266.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1266.jpg new file mode 100644 index 000000000..3df231c22 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1266.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1267.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1267.jpg new file mode 100644 index 000000000..9e179d0a9 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1267.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1268.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1268.jpg new file mode 100644 index 000000000..f5286c3db Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1268.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1269.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1269.jpg new file mode 100644 index 000000000..ee3f4a86b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1269.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1270.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1270.jpg new file mode 100644 index 000000000..0595076c7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1270.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1271.jpg b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1271.jpg new file mode 100644 index 000000000..9c6d6d74b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/dog/train_imgs_1271.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_1.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_1.jpg new file mode 100644 index 000000000..b816f9bc6 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_1.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_10.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_10.jpg new file mode 100644 index 000000000..a76ed177e Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_10.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_11.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_11.jpg new file mode 100644 index 000000000..744ae91fa Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_11.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_13.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_13.jpg new file mode 100644 index 000000000..d238b4f2a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_13.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_2.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_2.jpg new file mode 100644 index 000000000..f3a676599 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_2.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_3.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_3.jpg new file mode 100644 index 000000000..584afa327 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_3.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_5.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_5.jpg new file mode 100644 index 000000000..1d5a013f9 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_5.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_7.jpg b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_7.jpg new file mode 100644 index 000000000..f52ae690b Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/flying/train_imgs_7.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1272.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1272.jpg new file mode 100644 index 000000000..49684abb7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1272.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1273.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1273.jpg new file mode 100644 index 000000000..b58476139 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1273.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1274.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1274.jpg new file mode 100644 index 000000000..64b3ec66e Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1274.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1275.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1275.jpg new file mode 100644 index 000000000..eac1b5c8f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1275.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1276.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1276.jpg new file mode 100644 index 000000000..465464ddd Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1276.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1277.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1277.jpg new file mode 100644 index 000000000..db1a08d31 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1277.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1278.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1278.jpg new file mode 100644 index 000000000..3b1641b36 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1278.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1279.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1279.jpg new file mode 100644 index 000000000..923043eeb Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1279.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1280.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1280.jpg new file mode 100644 index 000000000..904ee40d4 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1280.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1281.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1281.jpg new file mode 100644 index 000000000..f9bbc85df Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1281.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1282.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1282.jpg new file mode 100644 index 000000000..90d6d9a55 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1282.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1428.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1428.jpg new file mode 100644 index 000000000..5d981c21f Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_1428.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2065.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2065.jpg new file mode 100644 index 000000000..f81ad3770 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2065.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2066.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2066.jpg new file mode 100644 index 000000000..21bf2f7d7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2066.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2067.jpg b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2067.jpg new file mode 100644 index 000000000..f93d313be Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sapiens/train_imgs_2067.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_609.jpg b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_609.jpg new file mode 100644 index 000000000..239adbfcc Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_609.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_612.jpg b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_612.jpg new file mode 100644 index 000000000..55a3480d0 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_612.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_614.jpg b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_614.jpg new file mode 100644 index 000000000..8723a30be Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_614.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_620.jpg b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_620.jpg new file mode 100644 index 000000000..e0974ef2e Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/sofa/train_imgs_620.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_17.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_17.jpg new file mode 100644 index 000000000..07f3213cc Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_17.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_19.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_19.jpg new file mode 100644 index 000000000..33aba5e89 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_19.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_21.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_21.jpg new file mode 100644 index 000000000..55cc84237 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_21.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_22.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_22.jpg new file mode 100644 index 000000000..182b9c374 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_22.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_23.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_23.jpg new file mode 100644 index 000000000..2a7768e41 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_23.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_24.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_24.jpg new file mode 100644 index 000000000..4d4973d0a Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_24.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_25.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_25.jpg new file mode 100644 index 000000000..e27117bd7 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_25.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_26.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_26.jpg new file mode 100644 index 000000000..60f378112 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_26.jpg differ diff --git a/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_478.jpg b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_478.jpg new file mode 100644 index 000000000..5a5131742 Binary files /dev/null and b/domainlab/zdata/vlcs_mini/sun/vehicle/train_imgs_478.jpg differ diff --git a/domainlab/zdata/ztest_files/aggret_res_test1 b/domainlab/zdata/ztest_files/aggret_res_test1 new file mode 100644 index 000000000..f53acf3ae --- /dev/null +++ b/domainlab/zdata/ztest_files/aggret_res_test1 @@ -0,0 +1,2 @@ +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 diff --git a/domainlab/zdata/ztest_files/aggret_res_test11 b/domainlab/zdata/ztest_files/aggret_res_test11 new file mode 100644 index 000000000..797cc5055 --- /dev/null +++ b/domainlab/zdata/ztest_files/aggret_res_test11 @@ -0,0 +1,9 @@ +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 +0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.8111111, 0.8232258, 0.6903785, 0.6903785, 0.71645665, 0.89284086 +1, Task1, diva, 2, caltech, 1, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8095455 +1, Task1, diva, 2, caltech, 2, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.82222223, 0.8609804, 0.6981304, 0.6981304, 0.7278397, 0.9361605 +0, Task2, hduva, 2, caltech, 1, "{'a': 1, 'b': 3}", 0.76, 0.76, 0.49, 0.56, 0.57, 0.76 +0, Task2, hduva, 2, caltech, 2, "{'a': 1, 'b': 3}", 0.81, 0.75, 0.45, 0.64, 0.75, 0.89 +1, Task2, hduva, 2, caltech, 1, "{'a': 2, 'b': 4}", 0.75, 0.81, 0.45, 0.54, 0.39, 0.88 +1, Task2, hduva, 2, caltech, 2, "{'a': 2, 'b': 4}", 0.73, 0.72, 0.51, 0.51, 0.6, 0.88 diff --git a/domainlab/zdata/ztest_files/aggret_res_test2 b/domainlab/zdata/ztest_files/aggret_res_test2 new file mode 100644 index 000000000..93104ef85 --- /dev/null +++ b/domainlab/zdata/ztest_files/aggret_res_test2 @@ -0,0 +1,5 @@ +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 +0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.8111111, 0.8232258, 0.6903785, 0.6903785, 0.71645665, 0.89284086 +2, Task1, diva, 2, caltech, 3, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.77397263, 0.82765615, 0.59528303, 0.59528303, 0.5953641, 0.74150944 +0, Task2, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 diff --git a/domainlab/zdata/ztest_files/aggret_res_test21 b/domainlab/zdata/ztest_files/aggret_res_test21 new file mode 100644 index 000000000..5bb677ba7 --- /dev/null +++ b/domainlab/zdata/ztest_files/aggret_res_test21 @@ -0,0 +1,23 @@ +param_index, method, algo, epos, te_d, seed, params, acc, precision, recall, specificity, f1, auroc +0, Task1, diva, 2, caltech, 1, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8098495 +0, Task1, diva, 2, caltech, 2, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.8111111, 0.8232258, 0.6903785, 0.6903785, 0.71645665, 0.89284086 +2, Task1, diva, 2, caltech, 3, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.77397263, 0.82765615, 0.59528303, 0.59528303, 0.5953641, 0.74150944 +2, Task1, diva, 2, caltech, 4, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.851917, 0.7569983, 0.8873113, 0.8173113, 0.7985473, 0.8769811 +2, Task1, diva, 2, caltech, 5, "{'gamma_y': 1688039, 'gamma_d': 265711}", 0.84, 0.85, 0.615, 0.62, 0.62, 0.74 +1, Task1, diva, 2, caltech, 1, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.75, 0.87068963, 0.5588235, 0.5588235, 0.53100574, 0.8095455 +1, Task1, diva, 2, caltech, 2, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.82222223, 0.8609804, 0.6981304, 0.6981304, 0.7278397, 0.9361605 +1, Task1, diva, 2, caltech, 3, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.85397263, 0.95765615, 0.67528303, 0.6728303, 0.6853641, 0.81150944 +1, Task1, diva, 2, caltech, 4, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.971917, 0.8869983, 0.9273113, 0.9273113, 0.8285473, 0.9369811 +1, Task1, diva, 2, caltech, 5, "{'gamma_y': 3648291, 'gamma_d': 320432}", 0.92, 0.91, 0.74, 0.75, 0.67, 0.8 +0, Task2, hduva, 2, caltech, 1, "{'gamma_y': 97228, 'zy_dim': 76}", 0.76, 0.76, 0.49, 0.56, 0.57, 0.76 +0, Task2, hduva, 2, caltech, 2, "{'gamma_y': 97228, 'zy_dim': 76}", 0.81, 0.75, 0.45, 0.64, 0.75, 0.89 +0, Task2, hduva, 2, caltech, 3, "{'gamma_y': 97228, 'zy_dim': 76}", 0.8251667, 0.104563385, 0.10817383, 0.90109926, 0.08242064, 0.519054 +0, Task2, hduva, 2, caltech, 4, "{'gamma_y': 97228, 'zy_dim': 76}", 0.97535366, 0.88569593, 0.87402904, 0.98618114, 0.87845683, 0.99118155 +0, Task2, hduva, 2, caltech, 5, "{'gamma_y': 97228, 'zy_dim': 76}", 0.82422227, 0.10658247, 0.1084048, 0.9009563, 0.08635866, 0.51927835 +1, Task2, hduva, 2, caltech, 1, "{'gamma_y': 196616, 'zy_dim': 68}", 0.75, 0.81, 0.45, 0.54, 0.39, 0.88 +1, Task2, hduva, 2, caltech, 2, "{'gamma_y': 196616, 'zy_dim': 68}", 0.73, 0.72, 0.51, 0.51, 0.6, 0.88 +1, Task2, hduva, 2, caltech, 1, "{'gamma_y': 113475, 'zy_dim': 48}", 0.8551667, 0.204563385, 0.20817383, 0.80109926, 0.15242064, 0.559054 +1, Task2, hduva, 2, caltech, 2, "{'gamma_y': 113475, 'zy_dim': 48}", 0.57535366, 0.52569593, 0.41402904, 0.68618114, 0.57845683, 0.89118155 +1, Task2, hduva, 2, caltech, 3, "{'gamma_y': 113475, 'zy_dim': 48}", 0.72422227, 0.20658247, 0.2084048, 0.7009563, 0.18635866, 0.61927835 +1, Task2, erm, 2, caltech, 1, "{}", 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 +1, Task2, erm, 2, caltech, 2, "{}", 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 diff --git a/domainlab/zdata/ztest_files/dummy_file.py b/domainlab/zdata/ztest_files/dummy_file.py new file mode 100644 index 000000000..e0c7faa27 --- /dev/null +++ b/domainlab/zdata/ztest_files/dummy_file.py @@ -0,0 +1,4 @@ +""" +I am a dummy file used in tests/test_git_tag.py +to produce a file which is not commited +""" diff --git a/domainlab/zdata/ztest_files/test_parameter_samples.csv b/domainlab/zdata/ztest_files/test_parameter_samples.csv new file mode 100644 index 000000000..609864f2f --- /dev/null +++ b/domainlab/zdata/ztest_files/test_parameter_samples.csv @@ -0,0 +1,2 @@ +,task,algo,params +0,diva,diva,"{'gamma_y': 10e5, 'gamma_d': 1e5}" diff --git a/examples/algos/demo_custom_model.py b/examples/algos/demo_custom_model.py deleted file mode 100644 index a7d25360e..000000000 --- a/examples/algos/demo_custom_model.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Template class to inherit from if user need custom neural network -""" - -from torch.nn import functional as F - -from domainlab.models.model_custom import AModelCustom -from domainlab.algos.builder_custom import make_basic_trainer - - -class ModelCustom(AModelCustom): - """ - Template class to inherit from if user need custom neural network - """ - @property - def dict_net_module_na2arg_na(self): - return {"net_predict": "my_custom_arg_name"} - - def cal_logit_y(self, tensor_x): - """ - calculate the logit for softmax classification - """ - logit_y = self.net_predict(tensor_x) - return logit_y - - def cal_loss(self, tensor_x, tensor_y, tensor_d, others=None): - """cal_loss. - - :param tensor_x: - :param tensor_y: - :param tensor_d: - """ - logit_y = self.net_predict(tensor_x) - if (tensor_y.shape[-1] == 1) | (len(tensor_y.shape) == 1): - y_target = tensor_y - else: - _, y_target = tensor_y.max(dim=1) - lc_y = F.cross_entropy(logit_y, y_target, reduction="none") - return lc_y - - -def get_node_na(): - """In your custom python file, this function has to be implemented - to return the custom algorithm builder""" - return make_basic_trainer(ModelCustom) diff --git a/examples/api/jigen_dann_transformer.py b/examples/api/jigen_dann_transformer.py new file mode 100644 index 000000000..54a81d041 --- /dev/null +++ b/examples/api/jigen_dann_transformer.py @@ -0,0 +1,83 @@ +""" +DomainLab API CODING +""" + +from torch import nn +from torchvision.models import vit_b_16 +from torchvision.models.feature_extraction import create_feature_extractor + +from domainlab.mk_exp import mk_exp +from domainlab.models.model_dann import mk_dann +from domainlab.models.model_jigen import mk_jigen +from domainlab.tasks import get_task + + +class VIT(nn.Module): + """ + Vision transformer as feature extractor + """ + + def __init__( + self, freeze=True, list_str_last_layer=["getitem_5"], len_last_layer=768 + ): + super().__init__() + self.nets = vit_b_16(pretrained=True) + if freeze: + # freeze all the network except the final layer, + # for fast code execution, set freeze=False + # in case of enough computation resources + for param in self.nets.parameters(): + param.requires_grad = False + self.features_vit_flatten = create_feature_extractor( + self.nets, return_nodes=list_str_last_layer + ) + + def forward(self, tensor_x): + """ + compute logits predicts + """ + out = self.features_vit_flatten(tensor_x)["getitem_5"] + return out + + +def test_transformer(): + """ + test mk experiment API + """ + # specify domain generalization task + task = get_task("mini_vlcs") + # specify neural network to use as feature extractor + net_feature = VIT(freeze=True) + # since the size of feature is 768 + net_classifier = nn.Linear(768, task.dim_y) + + # see documentation for each arguments below + model_dann = mk_dann( + net_classifier=net_classifier, + list_str_y=task.list_str_y)( + net_encoder=net_feature, + net_discriminator=nn.Linear(768, 2), + list_d_tr=["labelme", "sun"], + alpha=1.0, + ) + # see documentation for each argument below + model_jigen = mk_jigen( + list_str_y=task.list_str_y, + net_classifier=net_classifier)( + net_encoder=net_feature, + net_classifier_permutation=nn.Linear(768, 32), + coeff_reg=1.0, + n_perm=31, + ) + + model_jigen.extend(model_dann) # let Jigen decorate DANN + model = model_jigen + # make trainer for model, here we decorate trainer mldg with dial + exp = mk_exp( + task, model, trainer="mldg_dial", test_domain="caltech", batchsize=2, nocu=True + ) + exp.execute(num_epochs=2) + + +if __name__ == "__main__": + test_transformer() diff --git a/examples/benchmark/benchmark_blood_resnet.yaml b/examples/benchmark/benchmark_blood_resnet.yaml new file mode 100644 index 000000000..b10fd9364 --- /dev/null +++ b/examples/benchmark/benchmark_blood_resnet.yaml @@ -0,0 +1,129 @@ +# test benchmark config. + +test_domains: + - acevedo +#- mll +#- matek + +output_dir: zoutput/benchmarks/blood +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/task_blood2.py + dmem: False + lr: 5e-5 + epos: 500 + epos_min: 20 + es: 1 + bs: 32 + npath: examples/nets/resnet50domainbed.py + san_check: True + +Shared params: + num_shared_param_samples: 8 + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zd_dim: + reference: zy_dim + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + + +diva: # name + model: diva + # set nname_dom = nname when changing nname + npath_dom: examples/nets/resnet50domainbed.py + shared: + - gamma_y + - zx_dim + - zy_dim + - zd_dim + + hyperparameters: + gamma_d: + min: 1e4 + max: 1e6 + step: 10_000 + distribution: loguniform + +hduva: # name + model: hduva + + npath_encoder_x2topic_h: examples/nets/resnet50domainbed.py + npath_encoder_sandwich_x2h4zd: examples/nets/resnet50domainbed.py + shared: + - gamma_y + - zx_dim + - zy_dim + - zd_dim + +erm: # name + model: erm + +mldg: + model: erm + trainer: mldg + shared: + - gamma_reg + +dann: + model: dann + shared: + - gamma_reg + + +dial: # name + model: erm + trainer: dial + shared: + - gamma_reg + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform diff --git a/examples/benchmark/benchmark_mnist.yaml b/examples/benchmark/benchmark_mnist.yaml new file mode 100644 index 000000000..e5867ee2b --- /dev/null +++ b/examples/benchmark/benchmark_mnist.yaml @@ -0,0 +1,189 @@ +# test benchmark config. + +test_domains: + - 3 + - 0 + +output_dir: zoutput/benchmarks/mnist_benchmark +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +sampling_seed: 0 + +startseed: 0 +endseed: 2 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + task: mnistcolor10 + tr_d: [1, 2, 4] + dmem: False + lr: 0.001 + epos: 50 + es: 5 + bs: 64 + nname: conv_bn_pool_2 + san_check: True + + +Task1: # name + model: diva + # set nname_dom = nname when changing nname + nname_dom: conv_bn_pool_2 + + hyperparameters: + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 10_000 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +Task2: # name + model: hduva + + nname_encoder_x2topic_h: conv_bn_pool_2 + nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 + + hyperparameters: + # Same config as diva. + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +Task3: # name + model: erm + trainer: matchdg + + hyperparameters: + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity, for mnist, to avoid numerical issue with nan, set tau min to be 0.1 + tau: + min: 0.1 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + + # penalty weight for matching loss (Lambda in paper) + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task4: # name + model: jigen + grid_len: 3 + + hyperparameters: + # number of permutations + nperm: + distribution: categorical + values: + - 30 + - 31 + - 100 + datatype: int + + # probability of permutating the tiles of an image, pperm = 0 -> pure classification + pperm: + min: 0.1 + max: 0.5 + distribution: uniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + +Task5: # name + model: dann + + hyperparameters: + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task6: # name + model: erm + + +Task7: # name + model: erm_dial + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform diff --git a/examples/benchmark/benchmark_mnist_hard.yaml b/examples/benchmark/benchmark_mnist_hard.yaml new file mode 100644 index 000000000..39396ff3b --- /dev/null +++ b/examples/benchmark/benchmark_mnist_hard.yaml @@ -0,0 +1,283 @@ +# test benchmark config. + +test_domains: + - 1 + - 2 + +output_dir: zoutput/benchmarks/mnist_hard +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + task: mnistcolor10 + tr_d: [0, 3] + dmem: False + epos: 200 + es: 1 + bs: 32 + lr: 1e-3 + nname: conv_bn_pool_2 + nname_dom: conv_bn_pool_2 + nname_encoder_x2topic_h: conv_bn_pool_2 + nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 + san_check: True + +Shared params: + num_shared_param_samples: 8 + + gamma_y: + min: 1e4 + max: 1e6 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zd_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + +diva: # name + model: diva + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + + +hduva: # name + model: hduva + zx_dim: 0 + shared: + - gamma_y + - zy_dim + - zd_dim + + +matchdg: # name + model: erm + trainer: matchdg + shared: + - gamma_reg + + hyperparameters: + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + +jigen: # name + model: jigen + grid_len: 3 + shared: + - gamma_reg + + hyperparameters: + # number of permutations + nperm: + distribution: categorical + values: + - 30 + - 31 + - 100 + datatype: int + + # probability of permutating the tiles of an image, pperm = 0 -> pure classification + pperm: + min: 0.1 + max: 0.5 + distribution: uniform + + +dann: # name + model: dann + shared: + - gamma_reg + + +erm: # name + model: erm + + +dial: # name + model: erm + trainer: dial + shared: + - gamma_reg + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + +mldg: # name + model: erm + trainer: mldg + shared: + - gamma_reg + + +hduva_matchdg: # name + model: hduva + trainer: matchdg + zx_dim: 0 + + shared: + - gamma_y + - zy_dim + - zd_dim + - gamma_reg + + hyperparameters: + # Same config as diva. + + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + + +diva_dial: + # Parameters that are fixed for all runs of this task. + model: diva + trainer: dial + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + - gamma_reg + + # specification of parameters that shall vary + # between runs to analyze the sensitivity + # of this task w.r.t. these parameters. + hyperparameters: + # Each parameter must contain: + # - distribution (uniform | loguniform | normal | lognormal) + # - min and max if distribution is uniform or loguniform + # - mean and std if distribution is normal or lognormal + + # step is optional and defines discrete parameters + # with the given step size. + # If min/mean and step are integer valued, + # the hyperparameter is ensured to be integer valued too. + # Otherwise, it is a float and rounding errors can occur. + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + +# Each node containing the model property is considered as a task. +diva_mldg: # name + # Parameters that are fixed for all runs of this task. + model: diva + trainer: mldg + shared: + - gamma_y + - gamma_d + - gamma_reg + + +hduva_mldg: # name + model: hduva + trainer: mldg + shared: + - gamma_y + - zy_dim + - gamma_reg diff --git a/examples/benchmark/benchmark_mnist_shared_hyper_grid.yaml b/examples/benchmark/benchmark_mnist_shared_hyper_grid.yaml new file mode 100644 index 000000000..932e7124b --- /dev/null +++ b/examples/benchmark/benchmark_mnist_shared_hyper_grid.yaml @@ -0,0 +1,74 @@ +# test benchmark config. +mode: grid +test_domains: + - 3 + - 0 + +output_dir: zoutput/benchmarks/mnist_benchmark_grid + +startseed: 0 +endseed: 2 # currently included + + +Shared params: + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + num: 2 + datatype: int + + lr: + distribution: categorical + values: + - 1e-3 + - 1e-4 + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + task: mnistcolor10 + tr_d: [1, 2, 4] + dmem: False + epos: 2 + es: 5 + bs: 64 + nname: conv_bn_pool_2 + san_check: True + gamma_y: 5e4 + + +method_diva: # name + model: diva + zx_dim: 0 + zd_dim: 32 + shared: + - zy_dim + nname_dom: conv_bn_pool_2 + gamma_y: 1e4 + + hyperparameters: + gamma_d: + min: 1e4 + max: 1e6 + step: 1e5 + distribution: loguniform + datatype: float + num: 2 + +method_hduva: # name + model: hduva + + nname_encoder_x2topic_h: conv_bn_pool_2 + nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 + shared: + - zy_dim + zx_dim: 0 + zd_dim: 32 + +erm: + model: erm + shared: + - lr diff --git a/examples/benchmark/benchmark_pacs.yaml b/examples/benchmark/benchmark_pacs.yaml new file mode 100644 index 000000000..175c800f3 --- /dev/null +++ b/examples/benchmark/benchmark_pacs.yaml @@ -0,0 +1,187 @@ +# test benchmark config. + +test_domains: + - sketch + +output_dir: zoutput/benchmarks/pacs_benchmark +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/task_pacs_path_list.py + dmem: False + lr: 1e-5 + epos: 500 + es: 5 + bs: 64 + nname: alexnet + san_check: True + + +Task1: # name + model: diva + # set nname_dom = nname when changing nname + nname_dom: alexnet + + hyperparameters: + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 10_000 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +Task2: # name + model: hduva + + nname_encoder_x2topic_h: alexnet + nname_encoder_sandwich_x2h4zd: alexnet + + hyperparameters: + # Same config as diva. + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +Task3: # name + model: erm + trainer: matchdg + + hyperparameters: + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + + # penalty weight for matching loss (Lambda in paper) + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task4: # name + model: jigen + grid_len: 3 + + hyperparameters: + # number of permutations + nperm: + distribution: categorical + values: + - 30 + - 31 + - 100 + datatype: int + + # probability of permutating the tiles of an image, pperm = 0 -> pure classification + pperm: + min: 0.1 + max: 0.5 + distribution: uniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + +Task5: # name + model: dann + + hyperparameters: + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task6: # name + model: erm + + +Task7: # name + model: erm_dial + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform diff --git a/examples/benchmark/benchmark_pacs_resnet.yaml b/examples/benchmark/benchmark_pacs_resnet.yaml new file mode 100644 index 000000000..50b3483c6 --- /dev/null +++ b/examples/benchmark/benchmark_pacs_resnet.yaml @@ -0,0 +1,282 @@ +# PACS + +test_domains: + - sketch + +output_dir: zoutput/benchmarks/pacs_benchmark +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by #(test_domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +# note that num_shared_param_samples is independent from num_param_samples (they are not cartesian +# product) see details in https://github.com/marrlab/DomainLab/blob/master/docs/doc_benchmark.md + +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/task_pacs_path_list.py + lr: 5e-5 + epos: 500 + epos_min: 20 + es: 1 + bs: 32 + npath: examples/nets/resnet50domainbed.py + npath_encoder_x2topic_h: examples/nets/resnet50domainbed.py + npath_encoder_sandwich_x2h4zd: examples/nets/resnet50domainbed.py + npath_dom: examples/nets/resnet50domainbed.py + +Shared params: + num_shared_param_samples: 8 + gamma_y: + min: 1e4 + max: 1e6 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zd_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + +diva: # name + model: diva + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + + +hduva: # name + model: hduva + zx_dim: 0 + shared: + - gamma_y + - zy_dim + - zd_dim + + +matchdg: # name + model: erm + trainer: matchdg + shared: + - gamma_reg + + hyperparameters: + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + +jigen: # name + model: jigen + grid_len: 3 + shared: + - gamma_reg + + hyperparameters: + # number of permutations + nperm: + distribution: categorical + values: + - 30 + - 31 + - 100 + datatype: int + + # probability of permutating the tiles of an image, pperm = 0 -> pure classification + pperm: + min: 0.1 + max: 0.5 + distribution: uniform + + +dann: # name + model: dann + shared: + - gamma_reg + + +erm: # name + model: erm + + +dial: # name + model: erm + trainer: dial + shared: + - gamma_reg + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + +mldg: # name + model: erm + trainer: mldg + shared: + - gamma_reg + + +hduva_matchdg: # name + model: hduva + trainer: matchdg + zx_dim: 0 + + shared: + - gamma_y + - zy_dim + - zd_dim + - gamma_reg + + hyperparameters: + # Same config as diva. + + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + + +diva_dial: + # Parameters that are fixed for all runs of this task. + model: diva + trainer: dial + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + - gamma_reg + + # specification of parameters that shall vary + # between runs to analyze the sensitivity + # of this task w.r.t. these parameters. + hyperparameters: + # Each parameter must contain: + # - distribution (uniform | loguniform | normal | lognormal) + # - min and max if distribution is uniform or loguniform + # - mean and std if distribution is normal or lognormal + + # step is optional and defines discrete parameters + # with the given step size. + # If min/mean and step are integer valued, + # the hyperparameter is ensured to be integer valued too. + # Otherwise, it is a float and rounding errors can occur. + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + +# Each node containing the model property is considered as a task. +diva_mldg: # name + # Parameters that are fixed for all runs of this task. + model: diva + trainer: mldg + shared: + - gamma_y + - gamma_d + - gamma_reg + + +hduva_mldg: # name + model: hduva + trainer: mldg + shared: + - gamma_y + - zy_dim + - gamma_reg diff --git a/examples/benchmark/benchmark_pacs_resnet_combo.yaml b/examples/benchmark/benchmark_pacs_resnet_combo.yaml new file mode 100644 index 000000000..e2faeefa3 --- /dev/null +++ b/examples/benchmark/benchmark_pacs_resnet_combo.yaml @@ -0,0 +1,181 @@ +# PACS + +test_domains: + - sketch + +output_dir: zoutput/benchmarks/pacs_benchmark +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by #(test_domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +# note that num_shared_param_samples is independent from num_param_samples (they are not cartesian +# product) see details in https://github.com/marrlab/DomainLab/blob/master/docs/doc_benchmark.md + +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/task_pacs_aug.py + lr: 5e-5 + epos: 500 + epos_min: 20 + es: 1 + bs: 32 + npath: examples/nets/resnet50domainbed.py + npath_encoder_x2topic_h: examples/nets/resnet50domainbed.py + npath_encoder_sandwich_x2h4zd: examples/nets/resnet50domainbed.py + npath_dom: examples/nets/resnet50domainbed.py + +Shared params: + num_shared_param_samples: 8 + gamma_y: + min: 1e4 + max: 1e6 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zd_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + + +erm: # name + model: erm + + +hduva_matchdg: # name + model: hduva + trainer: matchdg + zx_dim: 0 + + shared: + - gamma_y + - zy_dim + - zd_dim + - gamma_reg + + hyperparameters: + # Same config as diva. + + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + + +diva_dial: + # Parameters that are fixed for all runs of this task. + model: diva + trainer: dial + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + - gamma_reg + + # specification of parameters that shall vary + # between runs to analyze the sensitivity + # of this task w.r.t. these parameters. + hyperparameters: + # Each parameter must contain: + # - distribution (uniform | loguniform | normal | lognormal) + # - min and max if distribution is uniform or loguniform + # - mean and std if distribution is normal or lognormal + + # step is optional and defines discrete parameters + # with the given step size. + # If min/mean and step are integer valued, + # the hyperparameter is ensured to be integer valued too. + # Otherwise, it is a float and rounding errors can occur. + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + +# Each node containing the model property is considered as a task. +diva_mldg: # name + # Parameters that are fixed for all runs of this task. + model: diva + trainer: mldg + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + - gamma_reg + +hduva_mldg: # name + model: hduva + trainer: mldg + zx_dim: 0 + shared: + - gamma_y + - zy_dim + - zd_dim + - gamma_reg diff --git a/examples/benchmark/benchmark_pacs_resnet_model.yaml b/examples/benchmark/benchmark_pacs_resnet_model.yaml new file mode 100644 index 000000000..7c9b9dbd7 --- /dev/null +++ b/examples/benchmark/benchmark_pacs_resnet_model.yaml @@ -0,0 +1,101 @@ +# PACS +test_domains: + - sketch + +output_dir: zoutput/benchmarks/pacs_benchmark_resnet50_model_only +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by #(test_domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +# note that num_shared_param_samples is independent from num_param_samples (they are not cartesian +# product) see details in https://github.com/marrlab/DomainLab/blob/master/docs/doc_benchmark.md + +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/task_pacs_aug.py + lr: 5e-5 + epos: 500 + epos_min: 5 + warmup: 20 + es: 2 + bs: 32 + npath: examples/nets/resnet50domainbed.py + +Shared params: + num_shared_param_samples: 9 + gamma_y: + min: 1e4 + max: 1e8 + step: 1000 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e8 + step: 1000 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + zd_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + datatype: int + + gamma_reg: + min: 0.01 + max: 100 + step: 0.01 + distribution: loguniform + +erm: # name + model: erm + + +diva: # name + model: diva + npath_dom: examples/nets/resnet50domainbed.py + shared: + - gamma_y + - gamma_d + - zx_dim + - zy_dim + - zd_dim + +hduva: # name + model: hduva + zx_dim: 0 + npath_encoder_x2topic_h: examples/nets/resnet50domainbed.py + npath_encoder_sandwich_x2h4zd: examples/nets/resnet50domainbed.py + shared: + - gamma_y + - zy_dim + - zd_dim + +dann: # name + model: dann + shared: + - gamma_reg diff --git a/examples/benchmark/benchmark_pacs_resnet_trainer.yaml b/examples/benchmark/benchmark_pacs_resnet_trainer.yaml new file mode 100644 index 000000000..185aa4dd4 --- /dev/null +++ b/examples/benchmark/benchmark_pacs_resnet_trainer.yaml @@ -0,0 +1,107 @@ +# PACS + +test_domains: + - sketch + +output_dir: zoutput/benchmarks/pacs_benchmark_resnet50_trainer_only +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by #(test_domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +# note that num_shared_param_samples is independent from num_param_samples (they are not cartesian +# product) see details in https://github.com/marrlab/DomainLab/blob/master/docs/doc_benchmark.md + +sampling_seed: 0 + +startseed: 0 +endseed: 5 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/task_pacs_aug.py + lr: 5e-5 + epos: 500 + epos_min: 5 + es: 2 + bs: 32 + npath: examples/nets/resnet50domainbed.py + +Shared params: + # sample more shared parameters to ensure range being covered in random sampling + num_shared_param_samples: 20 + gamma_reg: + min: 0.01 + max: 100 + step: 0.01 + distribution: loguniform + +erm: # name + model: erm + +matchdg: # name + model: erm + trainer: matchdg + shared: + - gamma_reg + + hyperparameters: + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + step: 0.01 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + +# The only transformation for JiGen allowed is normalization and image resize, no random flip, as the original code shows: +# https://github.com/fmcarlucci/JigenDG/blob/master/data/JigsawLoader.py +# adding random flip here will cause jigen to confuse with the image tile reshuffling. + +dial: # name + model: erm + trainer: dial + shared: + - gamma_reg + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 5 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + step: 0.00001 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + step: 0.001 + distribution: loguniform + + +mldg: # name + model: erm + trainer: mldg + shared: + - gamma_reg diff --git a/examples/benchmark/color_mnist_erm_vs_diva.yaml b/examples/benchmark/color_mnist_erm_vs_diva.yaml new file mode 100644 index 000000000..bccd63636 --- /dev/null +++ b/examples/benchmark/color_mnist_erm_vs_diva.yaml @@ -0,0 +1,68 @@ +# test benchmark config. + +test_domains: + - 1 + - 2 + +output_dir: zoutput/benchmarks/mnist_benchmark +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +num_param_samples: 8 +sampling_seed: 0 + +startseed: 0 +endseed: 2 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + task: mnistcolor10 + tr_d: [0, 3] + dmem: False + lr: 0.001 + epos: 500 + es: 1 + bs: 32 + nname: conv_bn_pool_2 + san_check: False + + +diva: # name + model: diva + # set nname_dom = nname when changing nname + nname_dom: conv_bn_pool_2 + + hyperparameters: + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 10_000 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +erm: # name + model: erm diff --git a/examples/yaml/demo_benchmark.yaml b/examples/benchmark/demo_benchmark.yaml similarity index 78% rename from examples/yaml/demo_benchmark.yaml rename to examples/benchmark/demo_benchmark.yaml index 8e1842a6d..72dca383c 100644 --- a/examples/yaml/demo_benchmark.yaml +++ b/examples/benchmark/demo_benchmark.yaml @@ -1,9 +1,5 @@ # Example benchmark config script. -# Arguments set here are passed to each task. -# Specifications inside the tasks taking precedence. -tpath: examples/tasks/task_vlcs.py # dataset - # list of all domains that are used as test domain # in a leave-one-out setup, i.e. for each run, # one domain from this list is chosen as test domain @@ -11,10 +7,10 @@ tpath: examples/tasks/task_vlcs.py # dataset # of the specified dataset. test_domains: - caltech - # - sun - # - labelme + - sun + - labelme -output_dir: zoutput/benchmarks/demo_benchmark +output_dir: zoutput/benchmarks/demo_benchmark00 # number of hyperparameter samples per task. # Thus, the total runs of each task are given @@ -25,8 +21,6 @@ num_param_samples: 2 # startseed and endseed, this benchmark is fully reproducible. sampling_seed: 1 # Optional -epos: 3 -bs: 2 # the seed is increased by +1 until it reaches endseed. # endseed is included, so in total startseed - endseed + 1 # different seeds are used to estimate the stochastic @@ -34,10 +28,17 @@ bs: 2 startseed: 1 endseed: 2 # currently included -# Each node containing the aname property is considered as a task. -Task_diva: # name +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + tpath: examples/tasks/task_vlcs.py # dataset + epos: 2 + bs: 2 + +# Each node containing the model property is considered as a task. +diva: # name # Parameters that are fixed for all runs of this task. - aname: diva + model: diva nname: alexnet npath_dom: examples/nets/resnet.py # specification of parameters that shall vary @@ -66,11 +67,11 @@ Task_diva: # name step: 1 distribution: loguniform -TaskHduva: # name - aname: hduva +hduva: # name + model: hduva npath: examples/nets/resnet.py - nname_topic_distrib_img2topic: conv_bn_pool_2 - nname_encoder_sandwich_layer_img2h4zd: conv_bn_pool_2 + nname_encoder_x2topic_h: conv_bn_pool_2 + nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 hyperparameters: gamma_y: @@ -86,6 +87,12 @@ TaskHduva: # name distribution: loguniform -Task_deep_all: - aname: deepall +erm: + model: erm nname: alexnet + +# set constant hyper-parameters +mldg: + model: ermmldg + nname: alexnet + gamma_reg: 0.03 diff --git a/examples/benchmark/demo_benchmark_mnist4test.yaml b/examples/benchmark/demo_benchmark_mnist4test.yaml new file mode 100644 index 000000000..fc98e5d90 --- /dev/null +++ b/examples/benchmark/demo_benchmark_mnist4test.yaml @@ -0,0 +1,72 @@ +# Example benchmark config script. + +# list of all domains that are used as test domain +# in a leave-one-out setup, i.e. for each run, +# one domain from this list is chosen as test domain +# while training is performed on all other domains +# of the specified dataset. +test_domains: + - 0 + +output_dir: zoutput/benchmarks/demo_benchmark00 + +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(test_domains) * num_param_samples * num_seeds (see below) +num_param_samples: 2 +# sets the seed for hyperparameter sampling. +# With this option and the experiment seeds from +# startseed and endseed, this benchmark is fully reproducible. +sampling_seed: 1 # Optional + +# the seed is increased by +1 until it reaches endseed. +# endseed is included, so in total startseed - endseed + 1 +# different seeds are used to estimate the stochastic +# variance. +startseed: 1 +endseed: 2 # currently included + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + task: mnistcolor10 + tr_d: [1, 2] + epos: 2 + bs: 2 + +# Each node containing the model property is considered as a task. +diva: # name + # Parameters that are fixed for all runs of this task. + model: diva + nname: conv_bn_pool_2 + nname_dom: conv_bn_pool_2 + # specification of parameters that shall vary + # between runs to analyze the sensitivity + # of this task w.r.t. these parameters. + hyperparameters: + # Each parameter must contain: + # - distribution (uniform | loguniform | normal | lognormal) + # - min and max if distribution is uniform or loguniform + # - mean and std if distribution is normal or lognormal + + # step is optional and defines discrete parameters + # with the given step size. + # If min/mean and step are integer valued, + # the hyperparameter is ensured to be integer valued too. + # Otherwise, it is a float and rounding errors can occur. + gamma_y: + min: 10e4 + max: 10e6 + step: 1 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 1 + distribution: loguniform + + +erm: + model: erm + nname: conv_bn_pool_2 diff --git a/examples/benchmark/demo_benchmark_pacs_small.yaml b/examples/benchmark/demo_benchmark_pacs_small.yaml new file mode 100644 index 000000000..4a277401b --- /dev/null +++ b/examples/benchmark/demo_benchmark_pacs_small.yaml @@ -0,0 +1,187 @@ +# test benchmark config. + +test_domains: + - sketch + +output_dir: zoutput/benchmarks/pacs_benchmark +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +num_param_samples: 2 +sampling_seed: 0 + +startseed: 0 +endseed: 1 # currently included + + + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + tpath: examples/tasks/demo_task_path_list_small.py + dmem: False + lr: 1e-5 + epos: 2 + es: 10 + bs: 2 + nname: alexnet + san_check: True + + +Task1: # name + model: diva + # set nname_dom = nname when changing nname + nname_dom: alexnet + + hyperparameters: + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + gamma_d: + min: 1e4 + max: 1e6 + step: 10_000 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +Task2: # name + model: hduva + + nname_encoder_x2topic_h: alexnet + nname_encoder_sandwich_x2h4zd: alexnet + + hyperparameters: + # Same config as diva. + gamma_y: + min: 1e4 + max: 2e5 + step: 100 + distribution: loguniform + + zx_dim: + min: 0 + max: 96 + step: 32 + distribution: uniform + + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + + zd_dim: + reference: zy_dim + +Task3: # name + model: erm + trainer: matchdg + + hyperparameters: + # Total number of epochs for contrastive loss + epochs_ctr: + min: 2 + max: 10 + step: 1 + distribution: uniform + + # factor to magnify cosine similarity + tau: + min: 0.01 + max: 1 + distribution: loguniform + + # Number of epochs before updating the match tensor + epos_per_match_update: + min: 1 + max: 20 + step: 1 + distribution: uniform + + # penalty weight for matching loss (Lambda in paper) + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task4: # name + model: jigen + grid_len: 3 + + hyperparameters: + # number of permutations + nperm: + distribution: categorical + values: + - 30 + - 31 + - 100 + datatype: int + + # probability of permutating the tiles of an image, pperm = 0 -> pure classification + pperm: + min: 0.1 + max: 0.5 + distribution: uniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + + +Task5: # name + model: dann + + hyperparameters: + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task6: # name + model: erm + + +Task7: # name + model: erm_dial + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform diff --git a/examples/benchmark/demo_shared_hyper_grid.yaml b/examples/benchmark/demo_shared_hyper_grid.yaml new file mode 100644 index 000000000..932e7124b --- /dev/null +++ b/examples/benchmark/demo_shared_hyper_grid.yaml @@ -0,0 +1,74 @@ +# test benchmark config. +mode: grid +test_domains: + - 3 + - 0 + +output_dir: zoutput/benchmarks/mnist_benchmark_grid + +startseed: 0 +endseed: 2 # currently included + + +Shared params: + zy_dim: + min: 32 + max: 96 + step: 32 + distribution: uniform + num: 2 + datatype: int + + lr: + distribution: categorical + values: + - 1e-3 + - 1e-4 + +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + ## dataset + task: mnistcolor10 + tr_d: [1, 2, 4] + dmem: False + epos: 2 + es: 5 + bs: 64 + nname: conv_bn_pool_2 + san_check: True + gamma_y: 5e4 + + +method_diva: # name + model: diva + zx_dim: 0 + zd_dim: 32 + shared: + - zy_dim + nname_dom: conv_bn_pool_2 + gamma_y: 1e4 + + hyperparameters: + gamma_d: + min: 1e4 + max: 1e6 + step: 1e5 + distribution: loguniform + datatype: float + num: 2 + +method_hduva: # name + model: hduva + + nname_encoder_x2topic_h: conv_bn_pool_2 + nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 + shared: + - zy_dim + zx_dim: 0 + zd_dim: 32 + +erm: + model: erm + shared: + - lr diff --git a/examples/benchmark/run_snakemake.sh b/examples/benchmark/run_snakemake.sh deleted file mode 100755 index 645d36f91..000000000 --- a/examples/benchmark/run_snakemake.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# -n: dry-run (A dry run is a software testing process where the effects of a possible failure are intentionally mitigated, For example, there is rsync utility for transfer data over some interface, but user can try rsync with dry-run option to check syntax and test communication without data transferring.) -# -p: print shell commands -# -d: specify working directory. This should be the DomainLab dir -# -s: snakefile -# -- configfile: configuration yaml file of the benchmark - -#snakemake -np -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" -export DOMAINLAB_CUDA_START_SEED=$1 - -snakemake --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" --keep-going --summary # this will give us a clue first what jobs will be run - -snakemake --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" --keep-going - -#snakemake --rerun-incomplete --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" - - -# print execution graph to pdf - -#snakemake --dag --forceall -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" | dot -Tpdf > dag.pdf - -#snakemake --rulegraph --forceall -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" | dot -Tpdf > rulegraph.pdf diff --git a/examples/conf/vlcs_diva_mldg_dial.yaml b/examples/conf/vlcs_diva_mldg_dial.yaml new file mode 100644 index 000000000..0701766ff --- /dev/null +++ b/examples/conf/vlcs_diva_mldg_dial.yaml @@ -0,0 +1,11 @@ +te_d: caltech # domain name of test domain +tpath: examples/tasks/task_vlcs.py # python file path to specify the task +bs: 2 # batch size +model: dann_diva # combine model DANN with DIVA +epos: 1 # number of epochs +trainer: mldg_dial # combine trainer MLDG and DIAL +gamma_reg: 1.0 # hyperparameter of DANN +gamma_y: 700000.0 # hyperparameter of diva +gamma_d: 100000.0 # hyperparameter of diva +npath: examples/nets/resnet.py # neural network for class classification +npath_dom: examples/nets/resnet.py # neural network for domain classification diff --git a/examples/conf4algo/dann.yaml b/examples/conf4algo/dann.yaml new file mode 100644 index 000000000..65b245730 --- /dev/null +++ b/examples/conf4algo/dann.yaml @@ -0,0 +1,3 @@ +--- # training with dann +model: dann +nname: alexnet diff --git a/examples/conf4algo/deepall.yaml b/examples/conf4algo/deepall.yaml new file mode 100644 index 000000000..a870467b0 --- /dev/null +++ b/examples/conf4algo/deepall.yaml @@ -0,0 +1,3 @@ +--- # training with erm +model: erm +nname: alexnet diff --git a/examples/conf4algo/diva.yaml b/examples/conf4algo/diva.yaml new file mode 100644 index 000000000..1e645ffeb --- /dev/null +++ b/examples/conf4algo/diva.yaml @@ -0,0 +1,6 @@ +--- # training with diva +model: diva +nname: conv_bn_pool_2 +nname_dom: conv_bn_pool_2 +gamma_y: 10e5 +gamma_d: 1e5 diff --git a/examples/conf4algo/hduva.yaml b/examples/conf4algo/hduva.yaml new file mode 100644 index 000000000..2c56929ee --- /dev/null +++ b/examples/conf4algo/hduva.yaml @@ -0,0 +1,6 @@ +--- # training with hduva +model: hduva +nname: conv_bn_pool_2 +nname_encoder_x2topic_h: conv_bn_pool_2 +nname_encoder_sandwich_x2h4zd: conv_bn_pool_2 +gamma_y: 7e5 diff --git a/examples/conf4algo/jigen.yaml b/examples/conf4algo/jigen.yaml new file mode 100644 index 000000000..833e6e9c8 --- /dev/null +++ b/examples/conf4algo/jigen.yaml @@ -0,0 +1,6 @@ +--- # training with jigen +model: jigen +nname: alexnet +pperm: 1 +nperm: 100 +grid_len: 3 diff --git a/examples/conf4algo/matchdg.yaml b/examples/conf4algo/matchdg.yaml new file mode 100644 index 000000000..b75e2f360 --- /dev/null +++ b/examples/conf4algo/matchdg.yaml @@ -0,0 +1,4 @@ +--- # training with matchdg +model: jigen +nname: alexnet +epochs_ctr: 3 diff --git a/examples/models/demo_custom_model.py b/examples/models/demo_custom_model.py new file mode 100644 index 000000000..a01de46f6 --- /dev/null +++ b/examples/models/demo_custom_model.py @@ -0,0 +1,27 @@ +""" +Template class to inherit for custom model +""" +import torch +from torch.nn import functional as F + +from domainlab.algos.builder_custom import make_basic_trainer +from domainlab.models.model_custom import AModelCustom + + +class ModelCustom(AModelCustom): + """ + Template class to inherit from if user need custom neural network + """ + @property + def dict_net_module_na2arg_na(self): + """ + we use this property to associate the module "net_aux" with commandline argument + "my_custom_arg_name", so that one could use "net_aux" while being transparent to + what exact backbone is used. + """ + return {"net_aux": "my_custom_arg_name"} + +def get_node_na(): + """In your custom python file, this function has to be implemented + to return the custom algorithm builder""" + return make_basic_trainer(ModelCustom) diff --git a/examples/nets/resnet.py b/examples/nets/resnet.py index 1001e931b..2afb3e119 100644 --- a/examples/nets/resnet.py +++ b/examples/nets/resnet.py @@ -1,5 +1,6 @@ import torch.nn as nn from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights from domainlab.compos.nn_zoo.nn import LayerId from domainlab.compos.nn_zoo.nn_torchvision import NetTorchVisionBase @@ -9,13 +10,18 @@ class ResNetBase(NetTorchVisionBase): """ Since ResNet can be fetched from torchvision """ + def fetch_net(self, flag_pretrain): """fetch_net. :param flag_pretrain: """ - self.net_torchvision = torchvisionmodels.resnet.resnet50( - pretrained=flag_pretrain) + if flag_pretrain: + self.net_torchvision = torchvisionmodels.resnet.resnet50( + weights=ResNet50_Weights.IMAGENET1K_V2 + ) + else: + self.net_torchvision = torchvisionmodels.resnet.resnet50(weights="None") # CHANGEME: user can modify this line to choose other neural # network architectures from 'torchvision.models' @@ -24,6 +30,7 @@ class ResNet4DeepAll(ResNetBase): """ change the size of the last layer """ + def __init__(self, flag_pretrain, dim_y): """__init__. diff --git a/examples/nets/resnet50-19c8e357Dassl.pth b/examples/nets/resnet50-19c8e357Dassl.pth new file mode 100644 index 000000000..7e6d8883d Binary files /dev/null and b/examples/nets/resnet50-19c8e357Dassl.pth differ diff --git a/examples/nets/resnet50domainbed.py b/examples/nets/resnet50domainbed.py new file mode 100644 index 000000000..3428b8b58 --- /dev/null +++ b/examples/nets/resnet50domainbed.py @@ -0,0 +1,117 @@ +""" +resnet50 modified as described in +https://arxiv.org/pdf/2007.01434.pdf appendix D +""" +from torch import nn +from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights + +from domainlab.compos.nn_zoo.nn import LayerId +from domainlab.compos.nn_zoo.nn_torchvision import NetTorchVisionBase + + +class CostumResNet(nn.Module): + """ + this costum resnet includes the modification described in + https://arxiv.org/pdf/2007.01434.pdf appendix D + + For the architecture “Resnet-50”, we replace the final (softmax) layer of a ResNet50 pretrained + on ImageNet and fine-tune. Observing that batch normalization interferes with domain + generalization algorithms (as different minibatches follow different distributions), + we freeze all batch normalization + layers before fine-tuning. We insert a dropout layer before the final linear layer. + """ + + def __init__(self, flag_pretrain): + super().__init__() + self.flag_pretrain = flag_pretrain + + if flag_pretrain: + resnet50 = torchvisionmodels.resnet.resnet50( + weights=ResNet50_Weights.IMAGENET1K_V2 + ) + else: + resnet50 = torchvisionmodels.resnet.resnet50(weights="None") + + # freez all batchnormalisation layers + for module in resnet50.modules(): + if module._get_name() == "BatchNorm2d": + module.requires_grad_(False) + + self.resnet50_first_part = nn.Sequential(*(list(resnet50.children())[:-1])) + self.dropout = nn.Dropout() + self.fc = list(resnet50.children())[-1] + + def forward(self, x_arg): + """forward function of the network""" + x_arg = self.resnet50_first_part(x_arg) + x_arg = self.dropout(x_arg) + x_arg = nn.Flatten()(x_arg) + x_arg = self.fc(x_arg) + return x_arg + + +# NetTorchVisionBase is interface defined in DomainLab +class ResNetBase(NetTorchVisionBase): + """ + Since ResNet can be fetched from torchvision + """ + + def fetch_net(self, flag_pretrain): + """fetch_net. + + :param flag_pretrain: + """ + self.net_torchvision = CostumResNet(flag_pretrain) + # CHANGEME: user can modify this line to choose other neural + # network architectures from 'torchvision.models' + + +class ResNet4DeepAll(ResNetBase): + """ + change the size of the last layer + """ + + def __init__(self, flag_pretrain, dim_y): + """__init__. + + :param flag_pretrain: + :param dim_y: + """ + super().__init__(flag_pretrain) + num_final_in = self.net_torchvision.fc.in_features + self.net_torchvision.fc = nn.Linear(num_final_in, dim_y) + # CHANGEME: user should change "fc" to their chosen neural + # network's last layer's name + + +class ResNetNoLastLayer(ResNetBase): + """ResNetNoLastLayer.""" + + def __init__(self, flag_pretrain): + """__init__. + + :param flag_pretrain: + """ + super().__init__(flag_pretrain) + self.net_torchvision.fc = LayerId() + # CHANGEME: user should change "fc" to their chosen neural + # network's last layer's name + + +# CHANGEME: user is required to implement the following function +# with **exact** signature to return a neural network architecture for +# classification of dim_y number of classes if remove_last_layer=False +# or return the same neural network without the last layer if +# remove_last_layer=False. +def build_feat_extract_net(dim_y, remove_last_layer): + """ + This function is compulsory to return a neural network feature extractor. + :param dim_y: number of classes to be classify can be None + if remove_last_layer = True + :param remove_last_layer: for resnet for example, whether + remove the last layer or not. + """ + if remove_last_layer: + return ResNetNoLastLayer(flag_pretrain=True) + return ResNet4DeepAll(flag_pretrain=True, dim_y=dim_y) diff --git a/examples/nets/resnetDassl.py b/examples/nets/resnetDassl.py new file mode 100644 index 000000000..9006a305f --- /dev/null +++ b/examples/nets/resnetDassl.py @@ -0,0 +1,74 @@ +import torch +import torch.nn as nn +from torchvision import models as torchvisionmodels + +from domainlab.compos.nn_zoo.nn import LayerId +from domainlab.compos.nn_zoo.nn_torchvision import NetTorchVisionBase + + +class ResNetBaseDassl(NetTorchVisionBase): + """ + Since ResNet can be fetched from torchvision + """ + + def fetch_net(self, flag_pretrain): + """fetch_net. + + :param flag_pretrain: + """ + self.net_torchvision = torchvisionmodels.resnet.resnet50(weights=None) + weights = "examples/nets/resnet50-19c8e357Dassl.pth" + # CHANGEME: user can modify this line to choose other neural + # network architectures from 'torchvision.models' + if flag_pretrain: + self.net_torchvision.load_state_dict(torch.load(weights)) + + +class ResNet4DeepAllDassl(ResNetBaseDassl): + """ + change the size of the last layer + """ + + def __init__(self, flag_pretrain, dim_y): + """__init__. + + :param flag_pretrain: + :param dim_y: + """ + super().__init__(flag_pretrain) + num_final_in = self.net_torchvision.fc.in_features + self.net_torchvision.fc = nn.Linear(num_final_in, dim_y) + # CHANGEME: user should change "fc" to their chosen neural + # network's last layer's name + + +class ResNetNoLastLayerDassl(ResNetBaseDassl): + """ResNetNoLastLayer.""" + + def __init__(self, flag_pretrain): + """__init__. + + :param flag_pretrain: + """ + super().__init__(flag_pretrain) + self.net_torchvision.fc = LayerId() + # CHANGEME: user should change "fc" to their chosen neural + # network's last layer's name + + +# CHANGEME: user is required to implement the following function +# with **exact** signature to return a neural network architecture for +# classification of dim_y number of classes if remove_last_layer=False +# or return the same neural network without the last layer if +# remove_last_layer=False. +def build_feat_extract_net(dim_y, remove_last_layer): + """ + This function is compulsory to return a neural network feature extractor. + :param dim_y: number of classes to be classify can be None + if remove_last_layer = True + :param remove_last_layer: for resnet for example, whether + remove the last layer or not. + """ + if remove_last_layer: + return ResNetNoLastLayerDassl(flag_pretrain=True) + return ResNet4DeepAllDassl(flag_pretrain=True, dim_y=dim_y) diff --git a/examples/nets/transformer.py b/examples/nets/transformer.py new file mode 100644 index 000000000..6e417f32d --- /dev/null +++ b/examples/nets/transformer.py @@ -0,0 +1,59 @@ +""" +make an experiment +""" + +from torch import nn +from torchvision.models import vit_b_16 +from torchvision.models.feature_extraction import create_feature_extractor + +from domainlab.mk_exp import mk_exp +from domainlab.models.model_erm import mk_erm +from domainlab.tasks import get_task + + +class VIT(nn.Module): + def __init__( + self, + num_cls, + freeze=True, + list_str_last_layer=["getitem_5"], + len_last_layer=768, + ): + super().__init__() + self.nets = vit_b_16(pretrained=True) + if freeze: + # freeze all the network except the final layer + for param in self.nets.parameters(): + param.requires_grad = False + self.features_vit_flatten = create_feature_extractor( + self.nets, return_nodes=list_str_last_layer + ) + self.fc = nn.Linear(len_last_layer, num_cls) + + def forward(self, tensor_x): + """ + compute logits predicts + """ + x = self.features_vit_flatten(tensor_x)["getitem_5"] + out = self.fc(x) + return out + + +def test_transformer(): + """ + test mk experiment API + """ + # specify domain generalization task + task = get_task("mini_vlcs") + # specify backbone to use + backbone = VIT(num_cls=task.dim_y, freeze=True) + model = mk_erm()(backbone) + # make trainer for model + exp = mk_exp( + task, model, trainer="mldg,dial", test_domain="caltech", batchsize=2, nocu=True + ) + exp.execute(num_epochs=2) + + +if __name__ == "__main__": + test_transformer() diff --git a/examples/tasks/demo_task_path_list_small.py b/examples/tasks/demo_task_path_list_small.py index c174c61fb..92425774a 100644 --- a/examples/tasks/demo_task_path_list_small.py +++ b/examples/tasks/demo_task_path_list_small.py @@ -1,63 +1,68 @@ +""" +Toy example on how to use TaskPathList, by subsample a small portion of PACS data +""" from torchvision import transforms + from domainlab.tasks.task_pathlist import mk_node_task_path_list from domainlab.tasks.utils_task import ImSize def get_task(na=None): + """ + specify task by providing list of training, test and validation paths + folder path is with respect to the current working directory + """ node = mk_node_task_path_list( - # specify image size, must be consistent with the transformation + # ## specify image size, must be consistent with the transformation isize=ImSize(3, 224, 224), - # specify the names for all classes to classify - list_str_y=["dog", "elephant", "giraffe", "guitar", - "horse", "house", "person"], - # give an index to each class to classify - dict_class_label2name={"1": "dog", - "2": "elephant", - "3": "giraffe", - "4": "guitar", - "5": "horse", - "6": "house", - "7": "person"}, - - ##################################################################### - # specify where to find the text file for each domain containing the - # relative path to corresponding images - - # folder data is with respect to the current working directory - - ### 1. specify the list of images used for training set - dict_d2filepath_list_img={ + # ## specify the names for all classes to classify + list_str_y=["dog", "elephant", "giraffe", "guitar", "horse", "house", "person"], + # ## give an index to each target class + dict_class_label_ind2name={ + "1": "dog", + "2": "elephant", + "3": "giraffe", + "4": "guitar", + "5": "horse", + "6": "house", + "7": "person", + }, + # ## specify where to find the text file containing path for each image + # ## the text file below only need to specify the relative path + # ## training + dict_d2filepath_list_img_tr={ "art_painting": "data/pacs_split/art_painting_10.txt", "cartoon": "data/pacs_split/cartoon_10.txt", "photo": "data/pacs_split/photo_10.txt", - "sketch": "data/pacs_split/sketch_10.txt"}, - - ### 2. specify the list of images used for test set + "sketch": "data/pacs_split/sketch_10.txt", + }, + # ## testing dict_d2filepath_list_img_te={ "art_painting": "data/pacs_split/art_painting_10.txt", "cartoon": "data/pacs_split/cartoon_10.txt", "photo": "data/pacs_split/photo_10.txt", - "sketch": "data/pacs_split/sketch_10.txt"}, - - ### 3. specify the list of images used for validation set + "sketch": "data/pacs_split/sketch_10.txt", + }, + # ## validation dict_d2filepath_list_img_val={ "art_painting": "data/pacs_split/art_painting_10.txt", "cartoon": "data/pacs_split/cartoon_10.txt", "photo": "data/pacs_split/photo_10.txt", - "sketch": "data/pacs_split/sketch_10.txt"}, - ##################################################################### - - # specify the (absolute or relative with respect to working directory - # of python) root folder storing the images of each domain: - # replace with the path where each domain of your pacs images are - # stored. + "sketch": "data/pacs_split/sketch_10.txt", + }, + # ## specify root folder storing the images of each domain: dict_domain2imgroot={ - 'art_painting': "data/pacs_mini_10", - 'cartoon': "data/pacs_mini_10", - 'photo': "data/pacs_mini_10", - 'sketch': "data/pacs_mini_10"}, - # specify the pytorch transformation you want to apply to the image - trans4all=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()])) + "art_painting": "data/pacs_mini_10", + "cartoon": "data/pacs_mini_10", + "photo": "data/pacs_mini_10", + "sketch": "data/pacs_mini_10", + }, + # ## specify the pytorch transformation you want to apply to the image + img_trans_tr=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + ) return node diff --git a/examples/tasks/not_a_demo_task_path_list.py b/examples/tasks/not_a_demo_task_path_list.py deleted file mode 100644 index f13e9b7a7..000000000 --- a/examples/tasks/not_a_demo_task_path_list.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -full data(images), as well as the txt file indicating the filenames of images can be -download from -- (https://domaingeneralization.github.io/#data) -- or (https://drive.google.com/drive/folders/0B6x7gtvErXgfUU1WcGY5SzdwZVk?resourcekey=0-2fvpQY_QSyJf2uIECzqPuQ) -""" - -from torchvision import transforms -from domainlab.tasks.task_pathlist import mk_node_task_path_list -from domainlab.tasks.utils_task import ImSize - - -def get_task(na=None): - node = mk_node_task_path_list( - isize=ImSize(3, 224, 224), - list_str_y=["dog", "elephant", "giraffe", "guitar", - "horse", "house", "person"], - dict_class_label2name={"1": "dog", - "2": "elephant", - "3": "giraffe", - "4": "guitar", - "5": "horse", - "6": "house", - "7": "person"}, - dict_d2filepath_list_img={ - "art_painting": "~/Documents/datasets/pacs_split/art_painting_train_kfold.txt", - "cartoon": "~/Documents/datasets/pacs_split/cartoon_train_kfold.txt", - "photo": "~/Documents/datasets/pacs_split/photo_train_kfold.txt", - "sketch": "~/Documents/datasets/pacs_split/sketch_train_kfold.txt"}, - - dict_d2filepath_list_img_te={ - "art_painting": "~/Documents/datasets/pacs_split/art_painting_train_kfold.txt", - "cartoon": "~/Documents/datasets/pacs_split/cartoon_train_kfold.txt", - "photo": "~/Documents/datasets/pacs_split/photo_train_kfold.txt", - "sketch": "~/Documents/datasets/pacs_split/sketch_train_kfold.txt"}, - - dict_d2filepath_list_img_val={ - "art_painting": "~/Documents/datasets/pacs_split/art_painting_crossval_kfold.txt", - "cartoon": "~/Documents/datasets/pacs_split/cartoon_train_kfold.txt", - "photo": "~/Documents/datasets/pacs_split/photo_train_kfold.txt", - "sketch": "~/Documents/datasets/pacs_split/sketch_train_kfold.txt"}, - - dict_domain2imgroot={ - 'art_painting': "~/Documents/datasets/pacs/raw", - 'cartoon': "~/Documents/datasets/pacs/raw", - 'photo': "~/Documents/datasets/pacs/raw", - 'sketch': "~/Documents/datasets/pacs/raw"}, - trans4all=transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor()])) # @FIXME: - # FIXME: 224 is already provided in image size - return node diff --git a/examples/tasks/task_blood2.py b/examples/tasks/task_blood2.py index 593e7e25c..5c5571c66 100644 --- a/examples/tasks/task_blood2.py +++ b/examples/tasks/task_blood2.py @@ -1,59 +1,101 @@ from torchvision import transforms + from domainlab.tasks.task_folder_mk import mk_task_folder from domainlab.tasks.utils_task import ImSize +IMG_SIZE = 224 + +trans = transforms.Compose( + [ + transforms.Resize((IMG_SIZE, IMG_SIZE)), + transforms.RandomResizedCrop(IMG_SIZE, scale=(0.7, 1.0)), + transforms.RandomHorizontalFlip(), + transforms.ColorJitter(0.3, 0.3, 0.3, 0.3), + transforms.RandomGrayscale(), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), + ] +) + +trans_te = transforms.Compose( + [ + transforms.Resize((IMG_SIZE, IMG_SIZE)), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), + ] +) -trans = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.RandomResizedCrop(224, scale=(0.7, 1.0)), - transforms.RandomHorizontalFlip(), - transforms.ColorJitter(0.3, 0.3, 0.3, 0.3), - transforms.RandomGrayscale(), - transforms.ToTensor(), - transforms.Normalize([0.485, 0.456, 0.406], - [0.229, 0.224, 0.225]) -]) - -trans_te = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.ToTensor(), - transforms.Normalize([0.485, 0.456, 0.406], - [0.229, 0.224, 0.225]) -]) - - -task = mk_task_folder(extensions={"dib": "jpg", "mllmar": "TIF", "amlmatek": "tiff"}, - list_str_y=["monocyte", "eosinophil", "basophil"], - dict_domain_folder_name2class={ - "dib": {"monocyte": "monocyte", - # "lymphocyte": "lym", - "basophil": "basophil", - "eosinophil": "eosinophil"}, - # "neutrophil": "neutrophil"}, - "mllmar": {"05-MONO": "monocyte", - "10-EOS": "eosinophil", - # "04-LGL": "lym", - # "11-STAB": "neutrophil" - "09-BASO":"basophil"}, - "amlmatek": {"EOS": "eosinophil", - "MON": "monocyte", - # "LYT": "lym", - # "NGB": "neutrophil" - "BAS": "basophil"}}, - dict_domain_img_trans={ - "dib": trans, - "mllmar": trans, - "amlmatek": trans, - }, - img_trans_te=trans_te, - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "amlmatek": "/storage/groups/qscd01/datasets/191024_AML_Matek/AML-Cytomorphology_LMU", - "mllmar": "/storage/groups/qscd01/datasets/190527_MLL_marr/Data", - "dib": "/storage/groups/qscd01/datasets/armingruber/PBC_dataset_normal_DIB/"}, - taskna="blood_mon_eos_bas") +TASK = mk_task_folder( + extensions={"acevedo": "jpg", "matek": "tiff", "mll": "tif"}, + list_str_y=[ + "basophil", + "erythroblast", + "metamyelocyte", + "myeloblast", + "neutrophil_band", + "promyelocyte", + "eosinophil", + "lymphocyte_typical", + "monocyte", + "myelocyte", + "neutrophil_segmented", + ], + dict_domain_folder_name2class={ + "acevedo": { + "basophil": "basophil", + "erythroblast": "erythroblast", + "metamyelocyte": "metamyelocyte", + "neutrophil_band": "neutrophil_band", + "promyelocyte": "promyelocyte", + "eosinophil": "eosinophil", + "lymphocyte_typical": "lymphocyte_typical", + "monocyte": "monocyte", + "myelocyte": "myelocyte", + "neutrophil_segmented": "neutrophil_segmented", + }, + "matek": { + "basophil": "basophil", + "erythroblast": "erythroblast", + "metamyelocyte": "metamyelocyte", + "myeloblast": "myeloblast", + "neutrophil_band": "neutrophil_band", + "promyelocyte": "promyelocyte", + "eosinophil": "eosinophil", + "lymphocyte_typical": "lymphocyte_typical", + "monocyte": "monocyte", + "myelocyte": "myelocyte", + "neutrophil_segmented": "neutrophil_segmented", + }, + "mll": { + "basophil": "basophil", + "erythroblast": "erythroblast", + "metamyelocyte": "metamyelocyte", + "myeloblast": "myeloblast", + "neutrophil_band": "neutrophil_band", + "promyelocyte": "promyelocyte", + "eosinophil": "eosinophil", + "lymphocyte_typical": "lymphocyte_typical", + "monocyte": "monocyte", + "myelocyte": "myelocyte", + "neutrophil_segmented": "neutrophil_segmented", + }, + }, + dict_domain_img_trans={ + "acevedo": trans, + "mll": trans, + "matek": trans, + }, + img_trans_te=trans_te, + isize=ImSize(3, IMG_SIZE, IMG_SIZE), + dict_domain2imgroot={ + "matek": "/lustre/groups/labs/marr/qscd01/datasets/armingruber/_Domains/Matek_cropped", + "mll": "/lustre/groups/labs/marr/qscd01/datasets/armingruber/_Domains/MLL_20221220", + "acevedo": "/lustre/groups/labs/marr/qscd01/datasets/armingruber/_Domains/Acevedo_cropped", + }, + taskna="blood_mon_eos_bas", +) def get_task(na=None): - return task + return TASK diff --git a/examples/tasks/task_dset_custom.py b/examples/tasks/task_dset_custom.py new file mode 100644 index 000000000..a5328cff0 --- /dev/null +++ b/examples/tasks/task_dset_custom.py @@ -0,0 +1,28 @@ +""" +example task construction: + Specify each domain by a training set and validation (can be None) +""" +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize + +task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") +task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), +) +task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), +) +task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), +) + + +def get_task(na=None): + return task diff --git a/examples/tasks/task_pacs_aug.py b/examples/tasks/task_pacs_aug.py new file mode 100644 index 000000000..6fc092dca --- /dev/null +++ b/examples/tasks/task_pacs_aug.py @@ -0,0 +1,77 @@ +""" +full data(images), as well as the txt file indicating the filenames of images can be +download from +- (https://domaingeneralization.github.io/#data) +- or (https://drive.google.com/drive/folders/0B6x7gtvErXgfUU1WcGY5SzdwZVk?resourcekey=0-2fvpQY_QSyJf2uIECzqPuQ) +""" + +from torchvision import transforms + +from domainlab.tasks.task_pathlist import mk_node_task_path_list +from domainlab.tasks.utils_task import ImSize + +# change this to absolute directory where you have the raw images from PACS, +G_PACS_RAW_PATH = "data/pacs/PACS" +# domainlab repository contain already the file names in data/pacs_split folder of domainlab + + +def get_task(na=None): + node = mk_node_task_path_list( + isize=ImSize(3, 224, 224), + list_str_y=["dog", "elephant", "giraffe", "guitar", "horse", "house", "person"], + dict_class_label_ind2name={ + "1": "dog", + "2": "elephant", + "3": "giraffe", + "4": "guitar", + "5": "horse", + "6": "house", + "7": "person", + }, + dict_d2filepath_list_img_tr={ + "art_painting": "data/pacs_split/art_painting_train_kfold.txt", + "cartoon": "data/pacs_split/cartoon_train_kfold.txt", + "photo": "data/pacs_split/photo_train_kfold.txt", + "sketch": "data/pacs_split/sketch_train_kfold.txt", + }, + dict_d2filepath_list_img_te={ + "art_painting": "data/pacs_split/art_painting_test_kfold.txt", + "cartoon": "data/pacs_split/cartoon_test_kfold.txt", + "photo": "data/pacs_split/photo_test_kfold.txt", + "sketch": "data/pacs_split/sketch_test_kfold.txt", + }, + dict_d2filepath_list_img_val={ + "art_painting": "data/pacs_split/art_painting_crossval_kfold.txt", + "cartoon": "data/pacs_split/cartoon_crossval_kfold.txt", + "photo": "data/pacs_split/photo_crossval_kfold.txt", + "sketch": "data/pacs_split/sketch_crossval_kfold.txt", + }, + dict_domain2imgroot={ + "art_painting": G_PACS_RAW_PATH, + "cartoon": G_PACS_RAW_PATH, + "photo": G_PACS_RAW_PATH, + "sketch": G_PACS_RAW_PATH, + }, + img_trans_tr=transforms.Compose( + [ + transforms.RandomResizedCrop(224, scale=(0.7, 1.0)), + transforms.RandomHorizontalFlip(), + transforms.ColorJitter(0.3, 0.3, 0.3, 0.3), + transforms.RandomGrayscale(), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ), + img_trans_te=transforms.Compose( + [ + transforms.Resize((224, 224)), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ), + ) + return node diff --git a/examples/tasks/task_pacs_aug_noflip_no_zoom.py b/examples/tasks/task_pacs_aug_noflip_no_zoom.py new file mode 100644 index 000000000..c1f8b45a8 --- /dev/null +++ b/examples/tasks/task_pacs_aug_noflip_no_zoom.py @@ -0,0 +1,76 @@ +""" +full data(images), as well as the txt file indicating the filenames of images can be +download from +- (https://domaingeneralization.github.io/#data) +- or (https://drive.google.com/drive/folders/0B6x7gtvErXgfUU1WcGY5SzdwZVk?resourcekey=0-2fvpQY_QSyJf2uIECzqPuQ) +""" + +from torchvision import transforms + +from domainlab.tasks.task_pathlist import mk_node_task_path_list +from domainlab.tasks.utils_task import ImSize + +# change this to absolute directory where you have the raw images from PACS, +G_PACS_RAW_PATH = "data/pacs/PACS" +# domainlab repository contain already the file names in data/pacs_split folder of domainlab + + +def get_task(na=None): + node = mk_node_task_path_list( + isize=ImSize(3, 224, 224), + list_str_y=["dog", "elephant", "giraffe", "guitar", "horse", "house", "person"], + dict_class_label_ind2name={ + "1": "dog", + "2": "elephant", + "3": "giraffe", + "4": "guitar", + "5": "horse", + "6": "house", + "7": "person", + }, + dict_d2filepath_list_img_tr={ + "art_painting": "data/pacs_split/art_painting_train_kfold.txt", + "cartoon": "data/pacs_split/cartoon_train_kfold.txt", + "photo": "data/pacs_split/photo_train_kfold.txt", + "sketch": "data/pacs_split/sketch_train_kfold.txt", + }, + dict_d2filepath_list_img_te={ + "art_painting": "data/pacs_split/art_painting_test_kfold.txt", + "cartoon": "data/pacs_split/cartoon_test_kfold.txt", + "photo": "data/pacs_split/photo_test_kfold.txt", + "sketch": "data/pacs_split/sketch_test_kfold.txt", + }, + dict_d2filepath_list_img_val={ + "art_painting": "data/pacs_split/art_painting_crossval_kfold.txt", + "cartoon": "data/pacs_split/cartoon_crossval_kfold.txt", + "photo": "data/pacs_split/photo_crossval_kfold.txt", + "sketch": "data/pacs_split/sketch_crossval_kfold.txt", + }, + dict_domain2imgroot={ + "art_painting": G_PACS_RAW_PATH, + "cartoon": G_PACS_RAW_PATH, + "photo": G_PACS_RAW_PATH, + "sketch": G_PACS_RAW_PATH, + }, + img_trans_tr=transforms.Compose( + [ + + transforms.ColorJitter(0.3, 0.3, 0.3, 0.3), + transforms.RandomGrayscale(), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ), + img_trans_te=transforms.Compose( + [ + transforms.Resize((224, 224)), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ), + ) + return node diff --git a/examples/tasks/task_pacs_no_aug_norm_only.py b/examples/tasks/task_pacs_no_aug_norm_only.py new file mode 100644 index 000000000..7a1897741 --- /dev/null +++ b/examples/tasks/task_pacs_no_aug_norm_only.py @@ -0,0 +1,73 @@ +""" +full data(images), as well as the txt file indicating the filenames of images can be +download from +- (https://domaingeneralization.github.io/#data) +- or (https://drive.google.com/drive/folders/0B6x7gtvErXgfUU1WcGY5SzdwZVk?resourcekey=0-2fvpQY_QSyJf2uIECzqPuQ) +""" + +from torchvision import transforms + +from domainlab.tasks.task_pathlist import mk_node_task_path_list +from domainlab.tasks.utils_task import ImSize + +# change this to absolute directory where you have the raw images from PACS, +G_PACS_RAW_PATH = "data/pacs/PACS" +# domainlab repository contain already the file names in data/pacs_split folder of domainlab + + +def get_task(na=None): + node = mk_node_task_path_list( + isize=ImSize(3, 224, 224), + list_str_y=["dog", "elephant", "giraffe", "guitar", "horse", "house", "person"], + dict_class_label_ind2name={ + "1": "dog", + "2": "elephant", + "3": "giraffe", + "4": "guitar", + "5": "horse", + "6": "house", + "7": "person", + }, + dict_d2filepath_list_img_tr={ + "art_painting": "data/pacs_split/art_painting_train_kfold.txt", + "cartoon": "data/pacs_split/cartoon_train_kfold.txt", + "photo": "data/pacs_split/photo_train_kfold.txt", + "sketch": "data/pacs_split/sketch_train_kfold.txt", + }, + dict_d2filepath_list_img_te={ + "art_painting": "data/pacs_split/art_painting_test_kfold.txt", + "cartoon": "data/pacs_split/cartoon_test_kfold.txt", + "photo": "data/pacs_split/photo_test_kfold.txt", + "sketch": "data/pacs_split/sketch_test_kfold.txt", + }, + dict_d2filepath_list_img_val={ + "art_painting": "data/pacs_split/art_painting_crossval_kfold.txt", + "cartoon": "data/pacs_split/cartoon_crossval_kfold.txt", + "photo": "data/pacs_split/photo_crossval_kfold.txt", + "sketch": "data/pacs_split/sketch_crossval_kfold.txt", + }, + dict_domain2imgroot={ + "art_painting": G_PACS_RAW_PATH, + "cartoon": G_PACS_RAW_PATH, + "photo": G_PACS_RAW_PATH, + "sketch": G_PACS_RAW_PATH, + }, + img_trans_tr=transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ), + img_trans_te=transforms.Compose( + [ + transforms.Resize((224, 224)), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] + ), + ] + ), + ) + return node diff --git a/examples/tasks/task_pacs_path_list.py b/examples/tasks/task_pacs_path_list.py new file mode 100644 index 000000000..045232b4a --- /dev/null +++ b/examples/tasks/task_pacs_path_list.py @@ -0,0 +1,62 @@ +""" +full data(images), as well as the txt file indicating the filenames of images can be +download from +- (https://domaingeneralization.github.io/#data) +- or (https://drive.google.com/drive/folders/0B6x7gtvErXgfUU1WcGY5SzdwZVk?resourcekey=0-2fvpQY_QSyJf2uIECzqPuQ) +""" + +from torchvision import transforms + +from domainlab.tasks.task_pathlist import mk_node_task_path_list +from domainlab.tasks.utils_task import ImSize + +# change this to absolute directory where you have the raw images from PACS, +G_PACS_RAW_PATH = "data/pacs/PACS" +# domainlab repository contain already the file names in data/pacs_split folder of domainlab + + +def get_task(na=None): + node = mk_node_task_path_list( + isize=ImSize(3, 224, 224), + list_str_y=["dog", "elephant", "giraffe", "guitar", "horse", "house", "person"], + dict_class_label_ind2name={ + "1": "dog", + "2": "elephant", + "3": "giraffe", + "4": "guitar", + "5": "horse", + "6": "house", + "7": "person", + }, + dict_d2filepath_list_img_tr={ + "art_painting": "data/pacs_split/art_painting_train_kfold.txt", + "cartoon": "data/pacs_split/cartoon_train_kfold.txt", + "photo": "data/pacs_split/photo_train_kfold.txt", + "sketch": "data/pacs_split/sketch_train_kfold.txt", + }, + dict_d2filepath_list_img_te={ + "art_painting": "data/pacs_split/art_painting_test_kfold.txt", + "cartoon": "data/pacs_split/cartoon_test_kfold.txt", + "photo": "data/pacs_split/photo_test_kfold.txt", + "sketch": "data/pacs_split/sketch_test_kfold.txt", + }, + dict_d2filepath_list_img_val={ + "art_painting": "data/pacs_split/art_painting_crossval_kfold.txt", + "cartoon": "data/pacs_split/cartoon_crossval_kfold.txt", + "photo": "data/pacs_split/photo_crossval_kfold.txt", + "sketch": "data/pacs_split/sketch_crossval_kfold.txt", + }, + dict_domain2imgroot={ + "art_painting": G_PACS_RAW_PATH, + "cartoon": G_PACS_RAW_PATH, + "photo": G_PACS_RAW_PATH, + "sketch": G_PACS_RAW_PATH, + }, + img_trans_tr=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + ) + return node diff --git a/examples/tasks/task_vlcs.py b/examples/tasks/task_vlcs.py index 5b14a50e9..3deb6b2d6 100644 --- a/examples/tasks/task_vlcs.py +++ b/examples/tasks/task_vlcs.py @@ -1,60 +1,63 @@ import os + from torchvision import transforms + from domainlab.tasks.task_folder_mk import mk_task_folder from domainlab.tasks.utils_task import ImSize # relative path is essential here since this file is used for testing, no absolute directory possible path_this_file = os.path.dirname(os.path.realpath(__file__)) -chain = mk_task_folder(extensions={"caltech": "jpg", "sun": - "jpg", "labelme": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", "stuhl": "chair"}, - "sun": {"vehicle": "car", "sofa": "chair"}, - "labelme": {"drive": "car", "sit": "chair"} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((256, 256)), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize( - [0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) - ]), - "sun": transforms.Compose( - [transforms.Resize((256, 256)), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize( - [0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) - ]), - "labelme": transforms.Compose( - [transforms.Resize((256, 256)), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize( - [0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) - ]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((256, 256)), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize( - [0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": os.path.join( - path_this_file, - "../../data/vlcs_mini/caltech/"), - "sun": os.path.join( - path_this_file, - "../../data/vlcs_mini/sun/"), - "labelme": os.path.join( - path_this_file, - "../../data/vlcs_mini/labelme/")}, - taskna="e_mini_vlcs") +chain = mk_task_folder( + extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, + list_str_y=["chair", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "stuhl": "chair"}, + "sun": {"vehicle": "car", "sofa": "chair"}, + "labelme": {"drive": "car", "sit": "chair"}, + }, + dict_domain_img_trans={ + "caltech": transforms.Compose( + [ + transforms.Resize((256, 256)), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ), + "sun": transforms.Compose( + [ + transforms.Resize((256, 256)), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ), + "labelme": transforms.Compose( + [ + transforms.Resize((256, 256)), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ), + }, + img_trans_te=transforms.Compose( + [ + transforms.Resize((256, 256)), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ), + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": os.path.join(path_this_file, "../../data/vlcs_mini/caltech/"), + "sun": os.path.join(path_this_file, "../../data/vlcs_mini/sun/"), + "labelme": os.path.join(path_this_file, "../../data/vlcs_mini/labelme/"), + }, + taskna="e_mini_vlcs", +) def get_task(na=None): diff --git a/examples/yaml/conf_diva_dial.yaml b/examples/yaml/conf_diva_dial.yaml new file mode 100644 index 000000000..04bcf4a93 --- /dev/null +++ b/examples/yaml/conf_diva_dial.yaml @@ -0,0 +1,11 @@ +--- # train diva with diva +te_d: caltech +tpath: examples/tasks/task_vlcs.py +bs: 2 +model: diva +epos: 3 # 3 epochs +trainer: dial +gamma_y: 700000.0 # +gamma_d: 100000.0 # +npath: examples/nets/resnet.py # path of neural network to use +npath_dom: examples/nets/resnet.py # path of neural network to use diff --git a/examples/yaml/demo.yaml b/examples/yaml/demo_config_single_run_diva.yaml similarity index 79% rename from examples/yaml/demo.yaml rename to examples/yaml/demo_config_single_run_diva.yaml index 523d8e361..c97b13775 100644 --- a/examples/yaml/demo.yaml +++ b/examples/yaml/demo_config_single_run_diva.yaml @@ -1,9 +1,9 @@ ---- # yaml demo document +--- # yaml demo document te_d: caltech tpath: examples/tasks/task_vlcs.py bs: 2 -aname: diva +model: diva debug: True gamma_y: 700000.0 #7e5 gamma_d: 100000.0 #1e5 diff --git a/examples/yaml/demo_hyperparameter_gridsearch.yml b/examples/yaml/demo_hyperparameter_gridsearch.yml new file mode 100644 index 000000000..478b7fd7f --- /dev/null +++ b/examples/yaml/demo_hyperparameter_gridsearch.yml @@ -0,0 +1,172 @@ +# only entries related to parameter sampling +output_dir: "zoutput/benchmarks/hyperparameter_grid_test" +mode: grid + +Shared params: + p1_shared: + distribution: uniform + min: 1 + max: 3 + step: 0 + num: 3 + + p2_shared: + distribution: normal + mean: 5 + std: 10 + step: 1 + num: 2 + +# currently, everything which contains the model property is considered as a task. +Task1: # name + model: Algo1 + # Each parameter must contain: + # - distribution + # - min and max if distribution is uniform or loguniform + # - mean and std if distribution is normal or lognormal + # - values and datatype if categorical + # OR + # reference, use this for equality constraints. + shared: + - p1_shared + - p2_shared + + hyperparameters: + p1: + distribution: uniform # uniform | loguniform | normal | lognormal | categorical + min: 1 # in case of uniform + max: 3 # in case of uniform + step: 0 # anything > 0 for discrete variables, 0 for continuous ones. Optional + num: 3 + + p2: + distribution: normal + mean: 1 # in case of normal + std: 2 # in case of normal + step: 1 # integer valued + num: 3 + datatype: int + + p3: + min: 1e-6 + max: 1 + distribution: loguniform + step: 0 + num: 3 + + p4: + # Value of p4 will always equal p3. + # Note that references to references are not supported + # and result in undefined behaviour. + # Is with the constraints, Python code is allowed in the reference. + reference: p3 + + p5: + reference: 2 * p3 / p1 + + p6: + distribution: normal + mean: 1 + std: 2 + step: 0 + num: 3 + + p7: + min: 0 + max: 1 + distribution: uniform + num: 1 + + p8: + min: 1e-6 + max: 1 + distribution: loguniform + num: 1 + + p9: + distribution: normal + mean: 0.5 + std: 2 + step: 1 + num: 3 + datatype: int + + p10: + distribution: normal + mean: 0.5 + std: 2 + step: 1 + num: 3 + + # Optional + constraints: + # In this list, any valid Python code evaluating to bool can be used. + # The parameters can be accessed by their name from above. + # Note that equality constraints should not be posed here, + # but enforced through references. + # Otherwise, the sampling will abort with error in most cases. + - "p1 < p2" + - "p3 < p2" + - "p1_shared == p1" + +Task2: # name + model: Algo2 + + hyperparameters: + p1: + mean: 1 + std: 3 + step: 2 # only odd numbers + distribution: lognormal + num: 3 + + p2: + min: -2 + max: 2 + step: 1 + distribution: uniform + num: 5 + + p3: + reference: 2*p2 + + p4: + distribution: categorical + values: + - 30.0 + - 31.0 + - 100.0 + datatype: int + + p5: + mean: 1 + std: 3 + distribution: lognormal + num: 4 + + p6: + mean: 1 + std: 3 + distribution: normal + num: 1 + +Task3: + model: Algo3 + zd_dim: 5 + + shared: + - p1_shared + + constraints: + - 'p1_shared <= 2' + +Task4: + model: Algo3 + zd_dim: 5 + + shared: + - p1_shared + +Task5: + model: Algo3 + zd_dim: 5 diff --git a/examples/yaml/demo_hyperparameter_sampling.yml b/examples/yaml/demo_hyperparameter_sampling.yml index 1e9e5c20d..fa3db8912 100644 --- a/examples/yaml/demo_hyperparameter_sampling.yml +++ b/examples/yaml/demo_hyperparameter_sampling.yml @@ -2,9 +2,24 @@ output_dir: "zoutput/benchmarks/hyperparameter_test" num_param_samples: 30 -# currently, everything which contains the aname property is considered as a task. + +Shared params: + num_shared_param_samples: 5 + p1_shared: + distribution: uniform + min: -3 + max: -1 + step: 0 + + p2_shared: + distribution: normal + mean: 5 + std: 10 + step: 1 + +# currently, everything which contains the model property is considered as a task. Task1: # name - aname: Algo1 + model: Algo1 # Each parameter must contain: # - distribution # - min and max if distribution is uniform or loguniform @@ -12,6 +27,9 @@ Task1: # name # - values and datatype if categorical # OR # reference, use this for equality constraints. + shared: + - p1_shared + - p2_shared hyperparameters: p1: distribution: uniform # uniform | loguniform | normal | lognormal | categorical @@ -50,9 +68,10 @@ Task1: # name # Otherwise, the sampling will abort with error in most cases. - "p1 < p2" - "p3 < p2" + - "p1_shared < p1" Task2: # name - aname: Algo2 + model: Algo2 hyperparameters: p1: @@ -73,11 +92,21 @@ Task2: # name p4: distribution: categorical values: - - 30 - - 31 - - 100 + - 30.0 + - 31.0 + - 100.0 datatype: int Task3: - aname: Algo3 - zd_dim: 5 \ No newline at end of file + model: Algo3 + zd_dim: 5 + + shared: + - p1_shared + + constraints: + - "p1_shared < -2" + +Task4: + model: Algo4 + zd_dim: 5 diff --git a/examples/yaml/demo_invalid_parameter.yaml b/examples/yaml/demo_invalid_parameter.yaml index 7701612f3..443e49b99 100644 --- a/examples/yaml/demo_invalid_parameter.yaml +++ b/examples/yaml/demo_invalid_parameter.yaml @@ -3,10 +3,10 @@ te_d: caltech tpath: examples/tasks/task_vlcs.py bs: 2 -aname: diva +model: diva debug: True gamma_y: 700000.0 #7e5 gamma_d: 100000.0 #1e5 nname: alexnet nname_dom: conv_bn_pool_2 -invalid_parameter: test \ No newline at end of file +invalid_parameter: test diff --git a/examples/yaml/demo_slurm_config_with_comments.yaml b/examples/yaml/demo_slurm_config_with_comments.yaml new file mode 100644 index 000000000..d251037dc --- /dev/null +++ b/examples/yaml/demo_slurm_config_with_comments.yaml @@ -0,0 +1,36 @@ +# This yaml file has been adapted from https://github.com/jdblischak/smk-simple-slurm +cluster: + mkdir -p logs/{rule} && + sbatch + --partition=gpu_p + # Put the job into the gpu partition + --qos=gpu + # Request a quality of service for the job. + --gres=gpu:1 + # Number of GPUs per node (gres=gpu:N) + --nice=10000 + # Run the job with an adjusted scheduling priority within Slurm. + -c 2 + # Allocating number of processes per task + --mem=60G + # RAM per node + --job-name=smk-{rule}-{wildcards} + # Specify name for job allocation + --output=logs/{rule}/{rule}-{wildcards}-%j.out + # Output file for logs +default-resources: + - partition=gpu_p + # Put the job into the gpu partition + - qos=gpu + # Request a quality of service for the job. + - mem_mb=1000 + # memory in MB a cluster node must provide +restart-times: 3 +max-jobs-per-second: 10 +max-status-checks-per-second: 1 +latency-wait: 60 +jobs: 500 +keep-going: True +printshellcmds: True +scheduler: greedy +use-conda: True diff --git a/examples/yaml/slurm/config.yaml b/examples/yaml/slurm/config.yaml new file mode 100644 index 000000000..e180df74d --- /dev/null +++ b/examples/yaml/slurm/config.yaml @@ -0,0 +1,27 @@ +# This yaml file has been adapted from https://github.com/jdblischak/smk-simple-slurm +cluster: + mkdir -p zoutput/slurm_logs/{rule} && + sbatch + --partition=gpu_p + --qos=gpu_normal + --gres=gpu:1 + --nice=10000 + -t 48:00:00 + -c 2 + --mem=160G + --job-name=smk-{rule}-{wildcards} + --output=zoutput/slurm_logs/{rule}/{rule}-{wildcards}-%j.out + --error=zoutput/slurm_logs/{rule}/{rule}-{wildcards}-%j.err +default-resources: + - partition=gpu_p + - qos=gpu_normal + - mem_mb=100000 +restart-times: 3 +max-jobs-per-second: 10 +max-status-checks-per-second: 1 +latency-wait: 60 +jobs: 20 +keep-going: True +printshellcmds: True +scheduler: greedy +use-conda: True diff --git a/examples/yaml/test_helm_benchmark.yaml b/examples/yaml/test_helm_benchmark.yaml new file mode 100644 index 000000000..606872f6f --- /dev/null +++ b/examples/yaml/test_helm_benchmark.yaml @@ -0,0 +1,96 @@ +# test benchmark config. + +tpath: examples/tasks/task_blood2.py # dataset + +test_domains: + - acevedo + - matek + - mll + +output_dir: zoutput/benchmarks/test_bloodcell_benchmark +dmem: False + +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +# +num_param_samples: 2 +# TODO set num of param samples +sampling_seed: 100 + +# use only 3 epochs to check if results can be aggregated +epos: 3 +bs: 16 +startseed: 1000 +endseed: 1000 # currently included + +# set all parameters to default first +nname: alexnet +san_check: False + +Task5: # name + model: dann + + hyperparameters: + early_stop: + distribution: categorical + datatype: int + values: + - 1 + - 5 + - 10 + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task6: # name + model: erm + + hyperparameters: + early_stop: + distribution: categorical + datatype: int + values: + - 1 + - 5 + - 10 + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task7: # name + model: erm_dial + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + early_stop: + distribution: categorical + datatype: int + values: + - 1 + - 5 + - 10 + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform diff --git a/examples/yaml/test_helm_pacs.yaml b/examples/yaml/test_helm_pacs.yaml new file mode 100644 index 000000000..4ec2d7ef7 --- /dev/null +++ b/examples/yaml/test_helm_pacs.yaml @@ -0,0 +1,71 @@ +# test benchmark config. + +# use only 3 epochs to check if results can be aggregated +domainlab_args: + # Domainlab arguments passed to each task. + # task specific arguments take precedence. + tpath: examples/tasks/not_a_demo_task_path_list.py # dataset + epos: 2 + bs: 16 + dmem: False + nname: alexnet + san_check: False + +test_domains: + - sketch + - art-painting + - photo + - cartoon + +output_dir: zoutput/benchmarks/test_pacs + +# number of hyperparameter samples per task. +# Thus, the total runs of each task are given +# by len(domains) * num_param_samples * num_seeds (see below) +# +num_param_samples: 2 +# TODO set num of param samples +sampling_seed: 100 + + +startseed: 1000 +endseed: 1000 # currently included + + + +Task5: # name + model: dann + + hyperparameters: + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform + +Task6: # name + model: erm + +Task7: # name + model: erm_dial + + hyperparameters: + dial_steps_perturb: + min: 1 + max: 10 + step: 1 + distribution: uniform + + dial_noise_scale: + min: 0.00001 + max: 0.1 + distribution: loguniform + + dial_epsilon: + min: 0.001 + max: 0.01 + distribution: loguniform + + gamma_reg: + min: 0.01 + max: 10 + distribution: loguniform diff --git a/gen_doc.sh b/gen_doc.sh index 199f5289f..c37e0faa0 100644 --- a/gen_doc.sh +++ b/gen_doc.sh @@ -1,5 +1,11 @@ #!/bin/bash # sphinx-quickstart +git checkout master +git pull +git checkout doc +git pull # get latest version of doc" +git merge master -m "merge master" + cd docs pip install -r requirements.txt sphinx-apidoc -f -o . ../domainlab # output path is current . directory (docs), module path @@ -7,6 +13,6 @@ make clean make html mkdir -p build/html/figs cp ./*.md build/html/ -cp ./figs/* build/html/figs +mkdir -p build/html/figs +cp -r ./figs/* build/html/figs # under docs directory, there is a empty html which point to the html generated by sphinx - diff --git a/main_out.py b/main_out.py index 9e84b6665..471702f9b 100644 --- a/main_out.py +++ b/main_out.py @@ -1,9 +1,9 @@ -from domainlab.compos.exp.exp_main import Exp -from domainlab.compos.exp.exp_cuda_seed import set_seed # reproducibility from domainlab.arg_parser import parse_cmd_args +from domainlab.cli import domainlab_cli +from domainlab.exp.exp_cuda_seed import set_seed # reproducibility +from domainlab.exp.exp_main import Exp +from domainlab.exp_protocol import aggregate_results +from domainlab.utils.generate_benchmark_plots import gen_benchmark_plots if __name__ == "__main__": - args = parse_cmd_args() - set_seed(args.seed) - exp = Exp(args=args) - exp.execute() + domainlab_cli() diff --git a/paper.md b/paper.md index 257e24ff9..b5eeed98f 100644 --- a/paper.md +++ b/paper.md @@ -147,6 +147,52 @@ constructing a concrete neural network architecture and feeding it into the mode and constructing the evaluator as a callback of what to do after each epoch. Experiment connect Task with Algorithm, which reside in module component, along with implementation of design patterns used for DomainLab and some neural network architectures as components of individual models. +## Summary +Deep learning (DL) models have solved real-world challenges in various areas, such as computer vision, natural language processing, and medical image classification or computational pathology. While generalizing to unseen test domains comes naturally to humans, it’s still a major obstacle for machines. By design, most DL models assume that training and testing distributions are the same, causing them to fail when this is violated. Instead, domain generalization aims at training domain invariant models that are robust to distribution shifts. + +We introduce DomainLab, a PyTorch based Python package for domain generalization. DomainLab focuses on causal domain generalization and probabilistic methods, while offering easy extensibility to a wide range of other methods including adversarial methods, self-supervised learning and other training paradigms. Compared to existing solutions, DomainLab uncouples the factors that contribute to the performance of a domain generalization method. How the data are split, which neural network architectures and loss functions are used, how the weights are updated, and which evaluation protocol is applied are defined independently. In that way, the user can take any combination and evaluate its impact on generalization performance. + +DomainLab’s documentation is hosted on https://marrlab.github.io/DomainLab and its source code can be found at https://github.com/marrlab/DomainLab. + +## Statement of need + +Over the past years, various methods have been proposed addressing different aspects of domain generalization. However, their implementations are often limited to proof-of-concept code, interspersed with custom code for data access, pre-processing, evaluation, etc. This limits the applicability of these methods, affects reproducibility, and restricts the ability to perform comparisons with other state-of-the-art methods. + +DomainBed for the first time provided a common codebase for benchmarking domain generalization methods (Gulrajani and Lopez-Paz 2020), however applying its algorithms to new use-cases requires extensive adaptation of its source code and the neural network backbones are hardcoded. The components of an algorithm have to be all initilalized in the construction function which is not suitable for complicated algorithms which require flexibility and plugin functionality of its components. More recently, we found a concurrent work Dassl, which provides a Python package to benchmark different algorithms such as semi-supervised learning, domain adaptation and domain generalization (Zhou et al. 2021). Its design is more modular than DomainBed. However the documentation does not contain enough details about algorithm implementation and the code base is not well tested. In addition, the authors have not clarified a plan for maintaining the module, while we aim at a long term maintenance of our package. + +With DomainLab, we introduce a fully modular Python package for domain generalization with Pytorch backend that follows best practices in software design and includes extensive documentation to enable the community to understand and contribute to the code. It contains extensive unit tests as well as end-to-end tests to verify the implemented functionality. + +An ideal package for domain generalization should decouple the factors that affectmodelperformance. This way, the components that contributed most to a promising result can be isolated, allowing for better comparability between methods. For example +Can the results be ascribed to a more appropriate neural network architecture? +Is the performance impacted by the protocol used to estimate the generalization performance, e.g. the dataset split? +Does the model benefit from a special loss function, e.g. because it offers a better regularization to the training of the neural network? + +## Description +### General Design +To address software design issues of existing code bases like DomainBed (Gulrajani and Lopez-Paz 2020) and Dassl (Zhou et al. 2021), and to maximally decouple factors that might affect the performance of domain generalization algorithms, we designed DomainLab with the following features: +First, the package offers the user a standalone application to specify the data, data split protocol , pre-processing, neural network backbone, and model loss function, which will not modify the code base of DomainLab. That is, it connects a user’s data to algorithms. +Domain generalization algorithms were implemented with a transparent underlying neural network architecture. The concrete neural network architecture can thus be replaced by plugging in an architecture implemented in a python file or by specifying a string of some existing neural network like AlexNet, via command line arguments. +Selection of algorithms, neural network components, as well as other components like training procedure are done via the chain-of-responsibility method. Other design patterns like observer pattern, visitor pattern, etc. are also used to improve the decoupling of different factors contributing to the performance of an algorithm (see also Section Components below). (Gamma book see below) +Instead of modifying code across several python files, the package is closed to modification and open to extension. To simply test an algorithm’s performance on `a user’s data, there is no need to change any code inside this repository, the user only needs to extend this repository to fit their requirement by providing custom python files. +It offers a framework for generating combinations by simply letting the user select elements through command line arguments. (combine tasks, neural network architectures) +With the above design, DomainLab offers users the flexibility to construct custom tasks with their own data, writing custom neural network architectures, and even trying their own algorithms by specifying a python file with custom loss functions. There is no need to change the original code of DomainLab when the user needs to use the domain generalization method to their own application, extend the method with custom neural network and try to discriminate the most significant factor that affects performance. +### Components +To achieve the above design goals of decoupling, we used the following components: +Models refer to a PyTorch module with a specified loss function containing regularization effect of several domains plus the task-specific loss, which is classification loss for classification task, but stay transparent with respect to the exact neural network architecture, which can be configured by the user via command line arguments. There are two types of models +implemented models from publications in the field of domain generalization using causality and probabilistic model based methods +custom models, where the user only needs to specify a python file defining the custom loss function, while remain transparent of the exact neural network used for each submodule. + The common classification loss calculation is done via a parent model class, thus the individual models representing different domain regularization can be reused for other tasks like segmentation by simply inheriting another task loss. +Tasks refer to a component, where the user specifies different datasets from different domains and preprocessing specified upon them. There are several types of tasks in DomainLab: +Built-in tasks like Color-Mnist, subsampled version of PACS, VLCS, as test utility of algorithms. +TaskFolder: If the data is already organized in a root folder, with different subfolders containing data from different domains and a further level of sub-sub-folders containing data from different classes. +TaskPathFile: This allows the user to specify each domain a text file indicating the path and label for each observation. Thus, the user can choose which portion of the sample to use as training, validation and test. + +Trainer is the component that directs data flow to the model to calculate loss and back-propagation to update the parameters; several models can share a common trainer. A specific trainer can also be a visitor to models to update coefficients in models during training to implement techniques like warm-up which follows the visitor design pattern from software engineering. +Following the observer pattern, we use separate classes to conduct operations needed to be done after each epoch (e.g. deciding whether to execute early stopping) and after training finishes. +Following the Builder Pattern, we construct each component needed to conduct a domain generalization experiment, including +constructing a trainer which guides the data flow. +constructing a concrete neural network architecture and feeding into the model. +constructing the evaluator as a callback of what to do after each epoch. ![DomainLab design architecture \label{fig:cdiagram}](./docs/libDG.svg "Design of DomainLab") diff --git a/poetry.lock b/poetry.lock index 9fa84ed7b..6e8b0c48e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8,23 +8,60 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "22.2.0" +version = "23.2.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "backpack-for-pytorch" +version = "1.6.0" +description = "BackPACK: Packing more into backprop" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +einops = ">=0.3.0,<1.0.0" +torch = ">=1.9.0" +torchvision = ">=0.7.0" +unfoldNd = ">=0.2.0,<1.0.0" [package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=0.971,<0.990)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests_no_zope = ["cloudpickle", "hypothesis", "mypy (>=0.971,<0.990)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["matplotlib", "memory-profiler", "sphinx-gallery", "sphinx-rtd-theme", "tabulate"] +lint = ["black", "darglint", "flake8", "flake8-bugbear", "flake8-comprehensions", "flake8-tidy-imports", "isort", "mccabe", "pep8-naming", "pycodestyle", "pydocstyle", "pyflakes"] +test = ["coveralls", "pytest (>=4.5.0,<5.0.0)", "pytest-benchmark (>=3.2.2,<4.0.0)", "pytest-cov", "pytest-optional-tests (>=0.1.1)", "scipy"] + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -32,58 +69,97 @@ python-versions = ">=3.6" [[package]] name = "charset-normalizer" -version = "3.0.1" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7.0" [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "contourpy" -version = "1.0.7" +version = "1.2.0" description = "Python library for calculating contours of 2D quadrilateral grids" category = "main" optional = false +python-versions = ">=3.9" + +[package.dependencies] +numpy = ">=1.20,<2.0" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "coverage" +version = "7.4.1" +description = "Code coverage measurement for Python" +category = "dev" +optional = false python-versions = ">=3.8" [package.dependencies] -numpy = ">=1.16" +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -bokeh = ["bokeh", "chromedriver", "selenium"] -docs = ["furo", "sphinx-copybutton"] -mypy = ["contourpy[bokeh]", "docutils-stubs", "mypy (==0.991)", "types-Pillow"] -test = ["Pillow", "matplotlib", "pytest"] -test-no-images = ["pytest"] +toml = ["tomli"] [[package]] name = "cycler" -version = "0.11.0" +version = "0.12.1" description = "Composable style cycles" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "einops" +version = "0.7.0" +description = "A new flavour of deep learning operations" +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +category = "main" +optional = false +python-versions = ">=3.8" + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] [[package]] name = "fonttools" -version = "4.38.0" +version = "4.47.2" description = "Tools to manipulate font files" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" [package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=14.0.0)", "xattr", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "scipy"] +interpolatable = ["munkres", "pycairo", "scipy"] lxml = ["lxml (>=4.0,<5)"] pathops = ["skia-pathops (>=0.5.0)"] plot = ["matplotlib"] @@ -91,12 +167,27 @@ repacker = ["uharfbuzz (>=0.23.0)"] symfont = ["sympy"] type1 = ["xattr"] ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=14.0.0)"] +unicode = ["unicodedata2 (>=15.1.0)"] woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] +[[package]] +name = "gdown" +version = "4.7.3" +description = "Google Drive direct download of big files." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +beautifulsoup4 = "*" +filelock = "*" +requests = {version = "*", extras = ["socks"]} +six = "*" +tqdm = "*" + [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -104,18 +195,18 @@ python-versions = ">=3.5" [[package]] name = "importlib-resources" -version = "5.10.2" +version = "6.1.1" description = "Read resources from Python packages" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] [[package]] name = "iniconfig" @@ -125,9 +216,17 @@ category = "dev" optional = false python-versions = ">=3.7" +[[package]] +name = "itermate" +version = "1.0.2" +description = "Iterator-tools for functional programming." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "joblib" -version = "1.2.0" +version = "1.3.2" description = "Lightweight pipelining with Python functions" category = "main" optional = false @@ -135,7 +234,7 @@ python-versions = ">=3.7" [[package]] name = "kiwisolver" -version = "1.4.4" +version = "1.4.5" description = "A fast implementation of the Cassowary constraint solver" category = "main" optional = false @@ -143,45 +242,44 @@ python-versions = ">=3.7" [[package]] name = "markdown-it-py" -version = "2.1.0" +version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" [package.dependencies] mdurl = ">=0.1,<1.0" [package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"] -code_style = ["pre-commit (==2.6)"] -compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistletoe (>=0.8.1,<0.9.0)", "mistune (>=2.0.2,<2.1.0)", "panflute (>=2.1.3,<2.2.0)"] -linkify = ["linkify-it-py (>=1.0,<2.0)"] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code_style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "matplotlib" -version = "3.7.0" +version = "3.8.2" description = "Python plotting package" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" [package.dependencies] contourpy = ">=1.0.1" cycler = ">=0.10" fonttools = ">=4.22.0" importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} -kiwisolver = ">=1.0.1" -numpy = ">=1.20" +kiwisolver = ">=1.3.1" +numpy = ">=1.21,<2" packaging = ">=20.0" -pillow = ">=6.2.0" +pillow = ">=8" pyparsing = ">=2.3.1" python-dateutil = ">=2.7" -setuptools_scm = ">=7" [[package]] name = "mdurl" @@ -193,15 +291,15 @@ python-versions = ">=3.7" [[package]] name = "numpy" -version = "1.24.2" +version = "1.26.3" description = "Fundamental package for array computing in Python" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" [[package]] name = "packaging" -version = "23.0" +version = "23.2" description = "Core utilities for Python packages" category = "main" optional = false @@ -228,20 +326,24 @@ pytz = ">=2020.1" test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] [[package]] -name = "Pillow" -version = "6.2.2" +name = "pillow" +version = "9.5.0" description = "Python Imaging Library (Fork)" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" [package.extras] dev = ["pre-commit", "tox"] @@ -257,18 +359,19 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "Pygments" -version = "2.14.0" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyparsing" -version = "3.0.9" +version = "3.1.1" description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "main" optional = false @@ -277,6 +380,14 @@ python-versions = ">=3.6.8" [package.extras] diagrams = ["jinja2", "railroad-diagrams"] +[[package]] +name = "PySocks" +version = "1.7.1" +description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + [[package]] name = "pytest" version = "6.2.5" @@ -298,6 +409,32 @@ toml = "*" [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-shell" +version = "0.3.2" +description = "A pytest plugin to help with testing shell scripts / black box commands" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +where = ">=1.0.2,<2.0.0" + [[package]] name = "python-dateutil" version = "2.8.2" @@ -311,7 +448,7 @@ six = ">=1.5" [[package]] name = "pytz" -version = "2022.7.1" +version = "2023.4" description = "World timezone definitions, modern and historical" category = "main" optional = false @@ -319,7 +456,7 @@ python-versions = "*" [[package]] name = "PyYAML" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" category = "main" optional = false @@ -327,17 +464,18 @@ python-versions = ">=3.6" [[package]] name = "requests" -version = "2.28.2" +version = "2.31.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7", optional = true, markers = "extra == \"socks\""} +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -345,85 +483,72 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.3.1" +version = "13.7.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "main" optional = false python-versions = ">=3.7.0" [package.dependencies] -markdown-it-py = ">=2.1.0,<3.0.0" -pygments = ">=2.14.0,<3.0.0" +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "scikit-learn" -version = "1.2.1" +version = "1.4.0" description = "A set of python modules for machine learning and data mining" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" [package.dependencies] -joblib = ">=1.1.1" -numpy = ">=1.17.3" -scipy = ">=1.3.2" +joblib = ">=1.2.0" +numpy = ">=1.19.5" +scipy = ">=1.6.0" threadpoolctl = ">=2.0.0" [package.extras] -benchmark = ["matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "pandas (>=1.0.5)"] -docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.10.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=4.0.1)", "sphinx-gallery (>=0.7.0)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] -examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.10.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"] -tests = ["black (>=22.3.0)", "flake8 (>=3.8.2)", "matplotlib (>=3.1.3)", "mypy (>=0.961)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=5.3.1)", "pytest-cov (>=2.9.0)", "scikit-image (>=0.16.2)"] +benchmark = ["matplotlib (>=3.3.4)", "memory-profiler (>=0.57.0)", "pandas (>=1.1.5)"] +docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.15.0)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] +examples = ["matplotlib (>=3.3.4)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)"] +tests = ["black (>=23.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.3)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "polars (>=0.19.12)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.0.272)", "scikit-image (>=0.17.2)"] [[package]] name = "scipy" -version = "1.9.3" +version = "1.12.0" description = "Fundamental algorithms for scientific computing in Python" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" [package.dependencies] -numpy = ">=1.18.5,<1.26.0" +numpy = ">=1.22.4,<1.29.0" [package.extras] -dev = ["flake8", "mypy", "pycodestyle", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-panels (>=0.5.2)", "sphinx-tabs"] -test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] -name = "setuptools" -version = "67.3.1" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "setuptools-scm" -version = "7.1.0" -description = "the blessed package to manage your versions by scm tags" +name = "seaborn" +version = "0.12.2" +description = "Statistical data visualization" category = "main" optional = false python-versions = ">=3.7" [package.dependencies] -packaging = ">=20.0" -setuptools = "*" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} -typing-extensions = "*" +matplotlib = ">=3.1,<3.6.1 || >3.6.1" +numpy = ">=1.17,<1.24.0 || >1.24.0" +pandas = ">=0.25" [package.extras] -test = ["pytest (>=6.2)", "virtualenv (>20)"] -toml = ["setuptools (>=42)"] +dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] +docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] +stats = ["scipy (>=1.3)", "statsmodels (>=0.10)"] [[package]] name = "six" @@ -433,13 +558,21 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +category = "main" +optional = false +python-versions = ">=3.8" + [[package]] name = "threadpoolctl" -version = "3.1.0" +version = "3.2.0" description = "threadpoolctl" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" [[package]] name = "toml" @@ -453,7 +586,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "main" +category = "dev" optional = false python-versions = ">=3.7" @@ -509,385 +642,569 @@ typing-extensions = "*" [package.extras] scipy = ["scipy"] +[[package]] +name = "tqdm" +version = "4.66.1" +description = "Fast, Extensible Progress Meter" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + [[package]] name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.9.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "unfoldNd" +version = "0.2.1" +description = "N-dimensional unfold (im2col) and fold (col2im) in PyTorch" category = "main" optional = false python-versions = ">=3.7" +[package.dependencies] +numpy = "*" +torch = "*" + +[package.extras] +lint = ["black", "darglint", "flake8", "flake8-bugbear", "flake8-comprehensions", "flake8-tidy-imports", "isort", "mccabe", "pep8-naming", "pycodestyle", "pydocstyle", "pyflakes"] +test = ["coveralls", "pytest", "pytest-cov", "pytest-optional-tests"] + [[package]] name = "urllib3" -version = "1.26.14" +version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.8" [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "where" +version = "1.0.2" +description = "Locates absolute file paths like the Windows 'where' or the Linux 'which' utility.\nMakes use of the PATH variable and the current directory." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +itermate = "1.0.2" [[package]] name = "zipp" -version = "3.13.0" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "b64c818a4ce27818393a8232f3873db6fabf86919d98debf3470f18ac0dae335" +content-hash = "a3783f6bafd96d72bec5f5a901546b3f628b2f92ad1a66131b526876a302dbf0" [metadata.files] atomicwrites = [ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, ] attrs = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] +backpack-for-pytorch = [ + {file = "backpack-for-pytorch-1.6.0.tar.gz", hash = "sha256:af6495b71bacf82a1c7cab01aa85bebabccfe74d87d89f108ea72a4a0d384de3"}, + {file = "backpack_for_pytorch-1.6.0-py3-none-any.whl", hash = "sha256:ac708dbb86dbb36f70fc81a1ccb1df5c7ba46d62bc9d10239d4b0e406ba41a6f"}, +] +beautifulsoup4 = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, ] certifi = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] charset-normalizer = [ - {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"}, - {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] colorama = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] contourpy = [ - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:95c3acddf921944f241b6773b767f1cbce71d03307270e2d769fd584d5d1092d"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc1464c97579da9f3ab16763c32e5c5d5bb5fa1ec7ce509a4ca6108b61b84fab"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8acf74b5d383414401926c1598ed77825cd530ac7b463ebc2e4f46638f56cce6"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c71fdd8f1c0f84ffd58fca37d00ca4ebaa9e502fb49825484da075ac0b0b803"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f99e9486bf1bb979d95d5cffed40689cb595abb2b841f2991fc894b3452290e8"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f4d8941a9564cda3f7fa6a6cd9b32ec575830780677932abdec7bcb61717b0"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9e20e5a1908e18aaa60d9077a6d8753090e3f85ca25da6e25d30dc0a9e84c2c6"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a877ada905f7d69b2a31796c4b66e31a8068b37aa9b78832d41c82fc3e056ddd"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6381fa66866b0ea35e15d197fc06ac3840a9b2643a6475c8fff267db8b9f1e69"}, - {file = "contourpy-1.0.7-cp310-cp310-win32.whl", hash = "sha256:3c184ad2433635f216645fdf0493011a4667e8d46b34082f5a3de702b6ec42e3"}, - {file = "contourpy-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:3caea6365b13119626ee996711ab63e0c9d7496f65641f4459c60a009a1f3e80"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed33433fc3820263a6368e532f19ddb4c5990855e4886088ad84fd7c4e561c71"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38e2e577f0f092b8e6774459317c05a69935a1755ecfb621c0a98f0e3c09c9a5"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae90d5a8590e5310c32a7630b4b8618cef7563cebf649011da80874d0aa8f414"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130230b7e49825c98edf0b428b7aa1125503d91732735ef897786fe5452b1ec2"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58569c491e7f7e874f11519ef46737cea1d6eda1b514e4eb5ac7dab6aa864d02"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d43960d809c4c12508a60b66cb936e7ed57d51fb5e30b513934a4a23874fae"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:152fd8f730c31fd67fe0ffebe1df38ab6a669403da93df218801a893645c6ccc"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9056c5310eb1daa33fc234ef39ebfb8c8e2533f088bbf0bc7350f70a29bde1ac"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a9d7587d2fdc820cc9177139b56795c39fb8560f540bba9ceea215f1f66e1566"}, - {file = "contourpy-1.0.7-cp311-cp311-win32.whl", hash = "sha256:4ee3ee247f795a69e53cd91d927146fb16c4e803c7ac86c84104940c7d2cabf0"}, - {file = "contourpy-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:5caeacc68642e5f19d707471890f037a13007feba8427eb7f2a60811a1fc1350"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd7dc0e6812b799a34f6d12fcb1000539098c249c8da54f3566c6a6461d0dbad"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0f9d350b639db6c2c233d92c7f213d94d2e444d8e8fc5ca44c9706cf72193772"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e96a08b62bb8de960d3a6afbc5ed8421bf1a2d9c85cc4ea73f4bc81b4910500f"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:031154ed61f7328ad7f97662e48660a150ef84ee1bc8876b6472af88bf5a9b98"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e9ebb4425fc1b658e13bace354c48a933b842d53c458f02c86f371cecbedecc"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb8f6d08ca7998cf59eaf50c9d60717f29a1a0a09caa46460d33b2924839dbd"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6c180d89a28787e4b73b07e9b0e2dac7741261dbdca95f2b489c4f8f887dd810"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b8d587cc39057d0afd4166083d289bdeff221ac6d3ee5046aef2d480dc4b503c"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:769eef00437edf115e24d87f8926955f00f7704bede656ce605097584f9966dc"}, - {file = "contourpy-1.0.7-cp38-cp38-win32.whl", hash = "sha256:62398c80ef57589bdbe1eb8537127321c1abcfdf8c5f14f479dbbe27d0322e66"}, - {file = "contourpy-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:57119b0116e3f408acbdccf9eb6ef19d7fe7baf0d1e9aaa5381489bc1aa56556"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30676ca45084ee61e9c3da589042c24a57592e375d4b138bd84d8709893a1ba4"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e927b3868bd1e12acee7cc8f3747d815b4ab3e445a28d2e5373a7f4a6e76ba1"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:366a0cf0fc079af5204801786ad7a1c007714ee3909e364dbac1729f5b0849e5"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ba9bb365446a22411f0673abf6ee1fea3b2cf47b37533b970904880ceb72f3"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b0bf0c30d432278793d2141362ac853859e87de0a7dee24a1cea35231f0d50"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7281244c99fd7c6f27c1c6bfafba878517b0b62925a09b586d88ce750a016d2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6d0f9e1d39dbfb3977f9dd79f156c86eb03e57a7face96f199e02b18e58d32a"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f6979d20ee5693a1057ab53e043adffa1e7418d734c1532e2d9e915b08d8ec2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5dd34c1ae752515318224cba7fc62b53130c45ac6a1040c8b7c1a223c46e8967"}, - {file = "contourpy-1.0.7-cp39-cp39-win32.whl", hash = "sha256:c5210e5d5117e9aec8c47d9156d1d3835570dd909a899171b9535cb4a3f32693"}, - {file = "contourpy-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:60835badb5ed5f4e194a6f21c09283dd6e007664a86101431bf870d9e86266c4"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ce41676b3d0dd16dbcfabcc1dc46090aaf4688fd6e819ef343dbda5a57ef0161"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a011cf354107b47c58ea932d13b04d93c6d1d69b8b6dce885e642531f847566"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31a55dccc8426e71817e3fe09b37d6d48ae40aae4ecbc8c7ad59d6893569c436"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f8ff4db108815addd900a74df665e135dbbd6547a8a69333a68e1f6e368ac2"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efe99298ba37e37787f6a2ea868265465410822f7bea163edcc1bd3903354ea9"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a1e97b86f73715e8670ef45292d7cc033548266f07d54e2183ecb3c87598888f"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc331c13902d0f50845099434cd936d49d7a2ca76cb654b39691974cb1e4812d"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24847601071f740837aefb730e01bd169fbcaa610209779a78db7ebb6e6a7051"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abf298af1e7ad44eeb93501e40eb5a67abbf93b5d90e468d01fc0c4451971afa"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:64757f6460fc55d7e16ed4f1de193f362104285c667c112b50a804d482777edd"}, - {file = "contourpy-1.0.7.tar.gz", hash = "sha256:d8165a088d31798b59e91117d1f5fc3df8168d8b48c4acc10fc0df0d0bdbcc5e"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, +] +coverage = [ + {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, + {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, + {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, + {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, + {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, + {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, + {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, + {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, + {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, + {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, + {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, + {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, + {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, ] cycler = [ - {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, - {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] +einops = [ + {file = "einops-0.7.0-py3-none-any.whl", hash = "sha256:0f3096f26b914f465f6ff3c66f5478f9a5e380bb367ffc6493a68143fbbf1fd1"}, + {file = "einops-0.7.0.tar.gz", hash = "sha256:b2b04ad6081a3b227080c9bf5e3ace7160357ff03043cd66cc5b2319eb7031d1"}, +] +filelock = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, ] fonttools = [ - {file = "fonttools-4.38.0-py3-none-any.whl", hash = "sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb"}, - {file = "fonttools-4.38.0.zip", hash = "sha256:2bb244009f9bf3fa100fc3ead6aeb99febe5985fa20afbfbaa2f8946c2fbdaf1"}, + {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df"}, + {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1"}, + {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c"}, + {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8"}, + {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670"}, + {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c"}, + {file = "fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0"}, + {file = "fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1"}, + {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b"}, + {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac"}, + {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c"}, + {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70"}, + {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e"}, + {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703"}, + {file = "fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c"}, + {file = "fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9"}, + {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635"}, + {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d"}, + {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb"}, + {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07"}, + {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71"}, + {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f"}, + {file = "fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085"}, + {file = "fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4"}, + {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:254d9a6f7be00212bf0c3159e0a420eb19c63793b2c05e049eb337f3023c5ecc"}, + {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eabae77a07c41ae0b35184894202305c3ad211a93b2eb53837c2a1143c8bc952"}, + {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86a5ab2873ed2575d0fcdf1828143cfc6b977ac448e3dc616bb1e3d20efbafa"}, + {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13819db8445a0cec8c3ff5f243af6418ab19175072a9a92f6cc8ca7d1452754b"}, + {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4e743935139aa485fe3253fc33fe467eab6ea42583fa681223ea3f1a93dd01e6"}, + {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d49ce3ea7b7173faebc5664872243b40cf88814ca3eb135c4a3cdff66af71946"}, + {file = "fonttools-4.47.2-cp38-cp38-win32.whl", hash = "sha256:94208ea750e3f96e267f394d5588579bb64cc628e321dbb1d4243ffbc291b18b"}, + {file = "fonttools-4.47.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f750037e02beb8b3569fbff701a572e62a685d2a0e840d75816592280e5feae"}, + {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d71606c9321f6701642bd4746f99b6089e53d7e9817fc6b964e90d9c5f0ecc6"}, + {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86e0427864c6c91cf77f16d1fb9bf1bbf7453e824589e8fb8461b6ee1144f506"}, + {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a00bd0e68e88987dcc047ea31c26d40a3c61185153b03457956a87e39d43c37"}, + {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d77479fb885ef38a16a253a2f4096bc3d14e63a56d6246bfdb56365a12b20c"}, + {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5465df494f20a7d01712b072ae3ee9ad2887004701b95cb2cc6dcb9c2c97a899"}, + {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4c811d3c73b6abac275babb8aa439206288f56fdb2c6f8835e3d7b70de8937a7"}, + {file = "fonttools-4.47.2-cp39-cp39-win32.whl", hash = "sha256:5b60e3afa9635e3dfd3ace2757039593e3bd3cf128be0ddb7a1ff4ac45fa5a50"}, + {file = "fonttools-4.47.2-cp39-cp39-win_amd64.whl", hash = "sha256:7ee48bd9d6b7e8f66866c9090807e3a4a56cf43ffad48962725a190e0dd774c8"}, + {file = "fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184"}, + {file = "fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3"}, +] +gdown = [ + {file = "gdown-4.7.3-py3-none-any.whl", hash = "sha256:aeb7b979b35efd007d0c12fee17350f007aeb5fa84a9def09381d765075ba9ce"}, + {file = "gdown-4.7.3.tar.gz", hash = "sha256:37edc3a0edda1a7fe5ebcc631c3aad0612582766460630ee52f481ba1ec7aefe"}, ] idna = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] importlib-resources = [ - {file = "importlib_resources-5.10.2-py3-none-any.whl", hash = "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6"}, - {file = "importlib_resources-5.10.2.tar.gz", hash = "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484"}, + {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, + {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, ] iniconfig = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +itermate = [ + {file = "itermate-1.0.2-py2-none-any.whl", hash = "sha256:00308991e0fe54465e0e0fbec4d47180b4f6df0f26c1e5d2ce3641e3373f28a0"}, + {file = "itermate-1.0.2.zip", hash = "sha256:5ee758cbb363493156cee7a29effc2b148a1a19d2be3097e92fc824991901e2a"}, +] joblib = [ - {file = "joblib-1.2.0-py3-none-any.whl", hash = "sha256:091138ed78f800342968c523bdde947e7a305b8594b910a0fea2ab83c3c6d385"}, - {file = "joblib-1.2.0.tar.gz", hash = "sha256:e1cee4a79e4af22881164f218d4311f60074197fb707e082e803b61f6d137018"}, + {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, + {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, ] kiwisolver = [ - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win32.whl", hash = "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win32.whl", hash = "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win32.whl", hash = "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win32.whl", hash = "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win32.whl", hash = "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"}, - {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] markdown-it-py = [ - {file = "markdown-it-py-2.1.0.tar.gz", hash = "sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"}, - {file = "markdown_it_py-2.1.0-py3-none-any.whl", hash = "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27"}, + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, ] matplotlib = [ - {file = "matplotlib-3.7.0-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:3da8b9618188346239e51f1ea6c0f8f05c6e218cfcc30b399dd7dd7f52e8bceb"}, - {file = "matplotlib-3.7.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c0592ba57217c22987b7322df10f75ef95bc44dce781692b4b7524085de66019"}, - {file = "matplotlib-3.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:21269450243d6928da81a9bed201f0909432a74e7d0d65db5545b9fa8a0d0223"}, - {file = "matplotlib-3.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb2e76cd429058d8954121c334dddfcd11a6186c6975bca61f3f248c99031b05"}, - {file = "matplotlib-3.7.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de20eb1247725a2f889173d391a6d9e7e0f2540feda24030748283108b0478ec"}, - {file = "matplotlib-3.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5465735eaaafd1cfaec3fed60aee776aeb3fd3992aa2e49f4635339c931d443"}, - {file = "matplotlib-3.7.0-cp310-cp310-win32.whl", hash = "sha256:092e6abc80cdf8a95f7d1813e16c0e99ceda8d5b195a3ab859c680f3487b80a2"}, - {file = "matplotlib-3.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:4f640534ec2760e270801056bc0d8a10777c48b30966eef78a7c35d8590915ba"}, - {file = "matplotlib-3.7.0-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:f336e7014889c38c59029ebacc35c59236a852e4b23836708cfd3f43d1eaeed5"}, - {file = "matplotlib-3.7.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a10428d4f8d1a478ceabd652e61a175b2fdeed4175ab48da4a7b8deb561e3fa"}, - {file = "matplotlib-3.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46ca923e980f76d34c1c633343a72bb042d6ba690ecc649aababf5317997171d"}, - {file = "matplotlib-3.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c849aa94ff2a70fb71f318f48a61076d1205c6013b9d3885ade7f992093ac434"}, - {file = "matplotlib-3.7.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:827e78239292e561cfb70abf356a9d7eaf5bf6a85c97877f254009f20b892f89"}, - {file = "matplotlib-3.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:691ef1f15360e439886186d0db77b5345b24da12cbc4fc57b26c4826db4d6cab"}, - {file = "matplotlib-3.7.0-cp311-cp311-win32.whl", hash = "sha256:21a8aeac39b4a795e697265d800ce52ab59bdeb6bb23082e2d971f3041074f02"}, - {file = "matplotlib-3.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:01681566e95b9423021b49dea6a2395c16fa054604eacb87f0f4c439750f9114"}, - {file = "matplotlib-3.7.0-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:cf119eee4e57389fba5ac8b816934e95c256535e55f0b21628b4205737d1de85"}, - {file = "matplotlib-3.7.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:21bd4033c40b95abd5b8453f036ed5aa70856e56ecbd887705c37dce007a4c21"}, - {file = "matplotlib-3.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:111ef351f28fd823ed7177632070a6badd6f475607122bc9002a526f2502a0b5"}, - {file = "matplotlib-3.7.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f91d35b3ef51d29d9c661069b9e4ba431ce283ffc533b981506889e144b5b40e"}, - {file = "matplotlib-3.7.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a776462a4a63c0bfc9df106c15a0897aa2dbab6795c693aa366e8e283958854"}, - {file = "matplotlib-3.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0dfd4a0cbd151f6439e6d7f8dca5292839ca311e7e650596d073774847ca2e4f"}, - {file = "matplotlib-3.7.0-cp38-cp38-win32.whl", hash = "sha256:56b7b79488209041a9bf7ddc34f1b069274489ce69e34dc63ae241d0d6b4b736"}, - {file = "matplotlib-3.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:8665855f3919c80551f377bc16df618ceabf3ef65270bc14b60302dce88ca9ab"}, - {file = "matplotlib-3.7.0-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:f910d924da8b9fb066b5beae0b85e34ed1b6293014892baadcf2a51da1c65807"}, - {file = "matplotlib-3.7.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:cf6346644e8fe234dc847e6232145dac199a650d3d8025b3ef65107221584ba4"}, - {file = "matplotlib-3.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d1e52365d8d5af699f04581ca191112e1d1220a9ce4386b57d807124d8b55e6"}, - {file = "matplotlib-3.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c869b646489c6a94375714032e5cec08e3aa8d3f7d4e8ef2b0fb50a52b317ce6"}, - {file = "matplotlib-3.7.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4ddac5f59e78d04b20469bc43853a8e619bb6505c7eac8ffb343ff2c516d72f"}, - {file = "matplotlib-3.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb0304c1cd802e9a25743414c887e8a7cd51d96c9ec96d388625d2cd1c137ae3"}, - {file = "matplotlib-3.7.0-cp39-cp39-win32.whl", hash = "sha256:a06a6c9822e80f323549c6bc9da96d4f233178212ad9a5f4ab87fd153077a507"}, - {file = "matplotlib-3.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:cb52aa97b92acdee090edfb65d1cb84ea60ab38e871ba8321a10bbcebc2a3540"}, - {file = "matplotlib-3.7.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3493b48e56468c39bd9c1532566dff3b8062952721b7521e1f394eb6791495f4"}, - {file = "matplotlib-3.7.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d0dcd1a0bf8d56551e8617d6dc3881d8a1c7fb37d14e5ec12cbb293f3e6170a"}, - {file = "matplotlib-3.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51fb664c37714cbaac69c16d6b3719f517a13c96c3f76f4caadd5a0aa7ed0329"}, - {file = "matplotlib-3.7.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4497d88c559b76da320b7759d64db442178beeea06a52dc0c629086982082dcd"}, - {file = "matplotlib-3.7.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9d85355c48ef8b9994293eb7c00f44aa8a43cad7a297fbf0770a25cdb2244b91"}, - {file = "matplotlib-3.7.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03eb2c8ff8d85da679b71e14c7c95d16d014c48e0c0bfa14db85f6cdc5c92aad"}, - {file = "matplotlib-3.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71b751d06b2ed1fd017de512d7439c0259822864ea16731522b251a27c0b2ede"}, - {file = "matplotlib-3.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b51ab8a5d5d3bbd4527af633a638325f492e09e45e78afdf816ef55217a09664"}, - {file = "matplotlib-3.7.0.tar.gz", hash = "sha256:8f6efd313430d7ef70a38a3276281cb2e8646b3a22b3b21eb227da20e15e6813"}, + {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"}, + {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"}, + {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"}, + {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"}, + {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"}, + {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"}, + {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"}, + {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"}, + {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"}, + {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"}, + {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"}, ] mdurl = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] numpy = [ - {file = "numpy-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d"}, - {file = "numpy-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5"}, - {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253"}, - {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978"}, - {file = "numpy-1.24.2-cp310-cp310-win32.whl", hash = "sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9"}, - {file = "numpy-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0"}, - {file = "numpy-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a"}, - {file = "numpy-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0"}, - {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281"}, - {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910"}, - {file = "numpy-1.24.2-cp311-cp311-win32.whl", hash = "sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95"}, - {file = "numpy-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04"}, - {file = "numpy-1.24.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2"}, - {file = "numpy-1.24.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5"}, - {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a"}, - {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96"}, - {file = "numpy-1.24.2-cp38-cp38-win32.whl", hash = "sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d"}, - {file = "numpy-1.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756"}, - {file = "numpy-1.24.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a"}, - {file = "numpy-1.24.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f"}, - {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb"}, - {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780"}, - {file = "numpy-1.24.2-cp39-cp39-win32.whl", hash = "sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468"}, - {file = "numpy-1.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f"}, - {file = "numpy-1.24.2.tar.gz", hash = "sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22"}, + {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"}, + {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"}, + {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"}, + {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"}, + {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"}, + {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"}, + {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"}, + {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"}, + {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"}, + {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"}, + {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"}, + {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"}, + {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"}, + {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"}, + {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"}, + {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"}, + {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"}, + {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"}, + {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"}, + {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"}, + {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"}, + {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"}, + {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"}, + {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"}, + {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"}, + {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"}, + {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"}, + {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"}, + {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"}, + {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"}, + {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"}, + {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"}, + {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"}, ] packaging = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] pandas = [ {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406"}, @@ -918,177 +1235,250 @@ pandas = [ {file = "pandas-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9"}, {file = "pandas-1.5.3.tar.gz", hash = "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1"}, ] -Pillow = [ - {file = "Pillow-6.2.2-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:834dd023b7f987d6b700ad93dc818098d7eb046bd445e9992b3093c6f9d7a95f"}, - {file = "Pillow-6.2.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:d3a98444a00b4643b22b0685dbf9e0ddcaf4ebfd4ea23f84f228adf5a0765bb2"}, - {file = "Pillow-6.2.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2b4a94be53dff02af90760c10a2e3634c3c7703410f38c98154d5ce71fe63d20"}, - {file = "Pillow-6.2.2-cp27-cp27m-win32.whl", hash = "sha256:87ef0eca169f7f0bc050b22f05c7e174a65c36d584428431e802c0165c5856ea"}, - {file = "Pillow-6.2.2-cp27-cp27m-win_amd64.whl", hash = "sha256:cbd5647097dc55e501f459dbac7f1d0402225636deeb9e0a98a8d2df649fc19d"}, - {file = "Pillow-6.2.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:4adc3302df4faf77c63ab3a83e1a3e34b94a6a992084f4aa1cb236d1deaf4b39"}, - {file = "Pillow-6.2.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e3a797a079ce289e59dbd7eac9ca3bf682d52687f718686857281475b7ca8e6a"}, - {file = "Pillow-6.2.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:bb7861e4618a0c06c40a2e509c1bea207eea5fd4320d486e314e00745a402ca5"}, - {file = "Pillow-6.2.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:535e8e0e02c9f1fc2e307256149d6ee8ad3aa9a6e24144b7b6e6fb6126cb0e99"}, - {file = "Pillow-6.2.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:bc149dab804291a18e1186536519e5e122a2ac1316cb80f506e855a500b1cdd4"}, - {file = "Pillow-6.2.2-cp35-cp35m-win32.whl", hash = "sha256:1a3bc8e1db5af40a81535a62a591fafdb30a8a1b319798ea8052aa65ef8f06d2"}, - {file = "Pillow-6.2.2-cp35-cp35m-win_amd64.whl", hash = "sha256:d6b4dc325170bee04ca8292bbd556c6f5398d52c6149ca881e67daf62215426f"}, - {file = "Pillow-6.2.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:43ef1cff7ee57f9c8c8e6fa02a62eae9fa23a7e34418c7ce88c0e3fe09d1fb38"}, - {file = "Pillow-6.2.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:900de1fdc93764be13f6b39dc0dd0207d9ff441d87ad7c6e97e49b81987dc0f3"}, - {file = "Pillow-6.2.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b83b380f9181cacc994f4c983d95a9c8b00b50bf786c66d235716b526a3332"}, - {file = "Pillow-6.2.2-cp36-cp36m-win32.whl", hash = "sha256:00e0bbe9923adc5cc38a8da7d87d4ce16cde53b8d3bba8886cb928e84522d963"}, - {file = "Pillow-6.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:5ccfcb0a34ad9b77ad247c231edb781763198f405a5c8dc1b642449af821fb7f"}, - {file = "Pillow-6.2.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:5dcbbaa3a24d091a64560d3c439a8962866a79a033d40eb1a75f1b3413bfc2bc"}, - {file = "Pillow-6.2.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6e2a7e74d1a626b817ecb7a28c433b471a395c010b2a1f511f976e9ea4363e64"}, - {file = "Pillow-6.2.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c424d35a5259be559b64490d0fd9e03fba81f1ce8e5b66e0a59de97547351d80"}, - {file = "Pillow-6.2.2-cp37-cp37m-win32.whl", hash = "sha256:aa4792ab056f51b49e7d59ce5733155e10a918baf8ce50f64405db23d5627fa2"}, - {file = "Pillow-6.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:0d5c99f80068f13231ac206bd9b2e80ea357f5cf9ae0fa97fab21e32d5b61065"}, - {file = "Pillow-6.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03457e439d073770d88afdd90318382084732a5b98b0eb6f49454746dbaae701"}, - {file = "Pillow-6.2.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ccf16fe444cc43800eeacd4f4769971200982200a71b1368f49410d0eb769543"}, - {file = "Pillow-6.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b72c39585f1837d946bd1a829a4820ccf86e361f28cbf60f5d646f06318b61e2"}, - {file = "Pillow-6.2.2-cp38-cp38-win32.whl", hash = "sha256:3ba7d8f1d962780f86aa747fef0baf3211b80cb13310fff0c375da879c0656d4"}, - {file = "Pillow-6.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:3e81485cec47c24f5fb27acb485a4fc97376b2b332ed633867dc68ac3077998c"}, - {file = "Pillow-6.2.2-pp273-pypy_73-win32.whl", hash = "sha256:aa1b0297e352007ec781a33f026afbb062a9a9895bb103c8f49af434b1666880"}, - {file = "Pillow-6.2.2-pp373-pypy36_pp73-win32.whl", hash = "sha256:82859575005408af81b3e9171ae326ff56a69af5439d3fc20e8cb76cd51c8246"}, - {file = "Pillow-6.2.2.tar.gz", hash = "sha256:db9ff0c251ed066d367f53b64827cc9e18ccea001b986d08c265e53625dab950"}, +pillow = [ + {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, + {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, + {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, + {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, + {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, + {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, + {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, + {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, + {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, + {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, + {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, + {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, + {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, + {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, + {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, + {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, + {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, + {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, + {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, + {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, + {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, + {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, + {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, + {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, + {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, + {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, + {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, ] pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] Pygments = [ - {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, - {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, +] +PySocks = [ + {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, + {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, + {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, ] pytest = [ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, ] +pytest-cov = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] +pytest-shell = [ + {file = "pytest-shell-0.3.2.tar.gz", hash = "sha256:7e30cf518a5271328f25eaa9013e1639607f169d7396a4b85204a8b34dacbab1"}, + {file = "pytest_shell-0.3.2-py3-none-any.whl", hash = "sha256:f60716134fc30e2c1fe9facb9fe60121d18b4d7b95e692b2c6f29271350aa12b"}, +] python-dateutil = [ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, ] pytz = [ - {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, - {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, + {file = "pytz-2023.4-py2.py3-none-any.whl", hash = "sha256:f90ef520d95e7c46951105338d918664ebfd6f1d995bd7d153127ce90efafa6a"}, + {file = "pytz-2023.4.tar.gz", hash = "sha256:31d4583c4ed539cd037956140d695e42c033a19e984bfce9964a3f7d59bc2b40"}, ] PyYAML = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] requests = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, ] rich = [ - {file = "rich-13.3.1-py3-none-any.whl", hash = "sha256:8aa57747f3fc3e977684f0176a88e789be314a99f99b43b75d1e9cb5dc6db9e9"}, - {file = "rich-13.3.1.tar.gz", hash = "sha256:125d96d20c92b946b983d0d392b84ff945461e5a06d3867e9f9e575f8697b67f"}, + {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, + {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, ] scikit-learn = [ - {file = "scikit-learn-1.2.1.tar.gz", hash = "sha256:fbf8a5c893c9b4b99bcc7ed8fb3e8500957a113f4101860386d06635520f7cfb"}, - {file = "scikit_learn-1.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bed9f75763bd392c094bf474c7ab75a01d68b15146ea7a20c0f9ff6fb3063dad"}, - {file = "scikit_learn-1.2.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:c9285275a435d1f8f47bbe3500346ab9ead2499e0e090518404d318ea90d1c1c"}, - {file = "scikit_learn-1.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc838b5a4057c55ba81b82316ea8bf443af445f96eb21500b0e40618017e0923"}, - {file = "scikit_learn-1.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8bcd303dd982494842a3f482f844d539484c6043b4eed896b43ea8e5f609a21"}, - {file = "scikit_learn-1.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:a9abf17d177df54e529154f26acfd42930e19117d045e8a9a8e893ca82dd94ec"}, - {file = "scikit_learn-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:70fa30d146b7e9d0c256e73e271b3e17f23123b7c4adcbde1a385031adf59090"}, - {file = "scikit_learn-1.2.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5a8111f3c7a314017ebf90d6feab861c11d1ca14f3dbafb39abcc31aa4c54ba6"}, - {file = "scikit_learn-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cba0c7c6bf1493f8ce670bab69f9317874826ee838988de377ae355abd4d74cf"}, - {file = "scikit_learn-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:479aedd0abedbda6b8b4529145fe4cd8622f69f726a72cef8f75548a93eeb1e1"}, - {file = "scikit_learn-1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:5523e21ab2b4d52b2bd41bedd335dbe8f3c1b5f6dd7c9c001b2e17ec9818af8d"}, - {file = "scikit_learn-1.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dcfab6a19b236194af88771d8e6e778a60c3339248ab0018696ebf2b7c8bed4b"}, - {file = "scikit_learn-1.2.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:559f66e12f93b34c8c85c0a5728c3b8af98f04eb12f2c9ee18ea3c82c3d2fad1"}, - {file = "scikit_learn-1.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbb7831b2308c67bb6dd83c5ea3cdaf8e8cafd2de4000b93d78bb689126bd2cf"}, - {file = "scikit_learn-1.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2c5d9930ced2b7821ad936b9940706ccb5471d89b8a516bb641cec87257d1c"}, - {file = "scikit_learn-1.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:54731e2c2fbff40da6d76cbb9022ace5f44a4020a10bd5cd92107e86882bad15"}, - {file = "scikit_learn-1.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d00e46a2a7fce6e118ed0f4c6263785bf6c297a94ffd0cd7b32455043c508cc8"}, - {file = "scikit_learn-1.2.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da0e2d50a8435ea8dc5cd21f1fc1a45d329bae03dcca92087ebed859d22d184e"}, - {file = "scikit_learn-1.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61bb9c654b5d2e6cdd4b1c7e6048fc66270c1682bda1b0f7d2726fdae09010f4"}, - {file = "scikit_learn-1.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0ee4d4d32c94e082344308528f7b3c9294b60ab19c84eb37a2d9c88bdffd9d1"}, - {file = "scikit_learn-1.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:c722f3446ad8c4f1a93b2399fe1a188635b94709a3f25e6f4d61efbe75fe8eaa"}, + {file = "scikit-learn-1.4.0.tar.gz", hash = "sha256:d4373c984eba20e393216edd51a3e3eede56cbe93d4247516d205643c3b93121"}, + {file = "scikit_learn-1.4.0-1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fce93a7473e2f4ee4cc280210968288d6a7d7ad8dc6fa7bb7892145e407085f9"}, + {file = "scikit_learn-1.4.0-1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d77df3d1e15fc37a9329999979fa7868ba8655dbab21fe97fc7ddabac9e08cc7"}, + {file = "scikit_learn-1.4.0-1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2404659fedec40eeafa310cd14d613e564d13dbf8f3c752d31c095195ec05de6"}, + {file = "scikit_learn-1.4.0-1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e98632da8f6410e6fb6bf66937712c949b4010600ccd3f22a5388a83e610cc3c"}, + {file = "scikit_learn-1.4.0-1-cp310-cp310-win_amd64.whl", hash = "sha256:11b3b140f70fbc9f6a08884631ae8dd60a4bb2d7d6d1de92738ea42b740d8992"}, + {file = "scikit_learn-1.4.0-1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8341eabdc754d5ab91641a7763243845e96b6d68e03e472531e88a4f1b09f21"}, + {file = "scikit_learn-1.4.0-1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d1f6bce875ac2bb6b52514f67c185c564ccd299a05b65b7bab091a4c13dde12d"}, + {file = "scikit_learn-1.4.0-1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c408b46b2fd61952d519ea1af2f8f0a7a703e1433923ab1704c4131520b2083b"}, + {file = "scikit_learn-1.4.0-1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b465dd1dcd237b7b1dcd1a9048ccbf70a98c659474324fa708464c3a2533fad"}, + {file = "scikit_learn-1.4.0-1-cp311-cp311-win_amd64.whl", hash = "sha256:0db8e22c42f7980fe5eb22069b1f84c48966f3e0d23a01afde5999e3987a2501"}, + {file = "scikit_learn-1.4.0-1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7eef6ea2ed289af40e88c0be9f7704ca8b5de18508a06897c3fe21e0905efdf"}, + {file = "scikit_learn-1.4.0-1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:349669b01435bc4dbf25c6410b0892073befdaec52637d1a1d1ff53865dc8db3"}, + {file = "scikit_learn-1.4.0-1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d439c584e58434d0350701bd33f6c10b309e851fccaf41c121aed55f6851d8cf"}, + {file = "scikit_learn-1.4.0-1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0e2427d9ef46477625ab9b55c1882844fe6fc500f418c3f8e650200182457bc"}, + {file = "scikit_learn-1.4.0-1-cp312-cp312-win_amd64.whl", hash = "sha256:d3d75343940e7bf9b85c830c93d34039fa015eeb341c5c0b4cd7a90dadfe00d4"}, + {file = "scikit_learn-1.4.0-1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:76986d22e884ab062b1beecdd92379656e9d3789ecc1f9870923c178de55f9fe"}, + {file = "scikit_learn-1.4.0-1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e22446ad89f1cb7657f0d849dcdc345b48e2d10afa3daf2925fdb740f85b714c"}, + {file = "scikit_learn-1.4.0-1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74812c9eabb265be69d738a8ea8d4884917a59637fcbf88a5f0e9020498bc6b3"}, + {file = "scikit_learn-1.4.0-1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad2a63e0dd386b92da3270887a29b308af4d7c750d8c4995dfd9a4798691bcc"}, + {file = "scikit_learn-1.4.0-1-cp39-cp39-win_amd64.whl", hash = "sha256:53b9e29177897c37e2ff9d4ba6ca12fdb156e22523e463db05def303f5c72b5c"}, + {file = "scikit_learn-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb8f044a8f5962613ce1feb4351d66f8d784bd072d36393582f351859b065f7d"}, + {file = "scikit_learn-1.4.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:a6372c90bbf302387792108379f1ec77719c1618d88496d0df30cb8e370b4661"}, + {file = "scikit_learn-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:785ce3c352bf697adfda357c3922c94517a9376002971bc5ea50896144bc8916"}, + {file = "scikit_learn-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0aba2a20d89936d6e72d95d05e3bf1db55bca5c5920926ad7b92c34f5e7d3bbe"}, + {file = "scikit_learn-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:2bac5d56b992f8f06816f2cd321eb86071c6f6d44bb4b1cb3d626525820d754b"}, + {file = "scikit_learn-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27ae4b0f1b2c77107c096a7e05b33458354107b47775428d1f11b23e30a73e8a"}, + {file = "scikit_learn-1.4.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5c5c62ffb52c3ffb755eb21fa74cc2cbf2c521bd53f5c04eaa10011dbecf5f80"}, + {file = "scikit_learn-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f0d2018ac6fa055dab65fe8a485967990d33c672d55bc254c56c35287b02fab"}, + {file = "scikit_learn-1.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a8918c415c4b4bf1d60c38d32958849a9191c2428ab35d30b78354085c7c7a"}, + {file = "scikit_learn-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:80a21de63275f8bcd7877b3e781679d2ff1eddfed515a599f95b2502a3283d42"}, + {file = "scikit_learn-1.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0f33bbafb310c26b81c4d41ecaebdbc1f63498a3f13461d50ed9a2e8f24d28e4"}, + {file = "scikit_learn-1.4.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:8b6ac1442ec714b4911e5aef8afd82c691b5c88b525ea58299d455acc4e8dcec"}, + {file = "scikit_learn-1.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05fc5915b716c6cc60a438c250108e9a9445b522975ed37e416d5ea4f9a63381"}, + {file = "scikit_learn-1.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:842b7d6989f3c574685e18da6f91223eb32301d0f93903dd399894250835a6f7"}, + {file = "scikit_learn-1.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:88bcb586fdff865372df1bc6be88bb7e6f9e0aa080dab9f54f5cac7eca8e2b6b"}, + {file = "scikit_learn-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f77674647dd31f56cb12ed13ed25b6ed43a056fffef051715022d2ebffd7a7d1"}, + {file = "scikit_learn-1.4.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:833999872e2920ce00f3a50839946bdac7539454e200eb6db54898a41f4bfd43"}, + {file = "scikit_learn-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:970ec697accaef10fb4f51763f3a7b1250f9f0553cf05514d0e94905322a0172"}, + {file = "scikit_learn-1.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:923d778f378ebacca2c672ab1740e5a413e437fb45ab45ab02578f8b689e5d43"}, + {file = "scikit_learn-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:1d041bc95006b545b59e458399e3175ab11ca7a03dc9a74a573ac891f5df1489"}, ] scipy = [ - {file = "scipy-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1884b66a54887e21addf9c16fb588720a8309a57b2e258ae1c7986d4444d3bc0"}, - {file = "scipy-1.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:83b89e9586c62e787f5012e8475fbb12185bafb996a03257e9675cd73d3736dd"}, - {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a72d885fa44247f92743fc20732ae55564ff2a519e8302fb7e18717c5355a8b"}, - {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01e1dd7b15bd2449c8bfc6b7cc67d630700ed655654f0dfcf121600bad205c9"}, - {file = "scipy-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:68239b6aa6f9c593da8be1509a05cb7f9efe98b80f43a5861cd24c7557e98523"}, - {file = "scipy-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b41bc822679ad1c9a5f023bc93f6d0543129ca0f37c1ce294dd9d386f0a21096"}, - {file = "scipy-1.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:90453d2b93ea82a9f434e4e1cba043e779ff67b92f7a0e85d05d286a3625df3c"}, - {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c06e62a390a9167da60bedd4575a14c1f58ca9dfde59830fc42e5197283dab"}, - {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb"}, - {file = "scipy-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:06d2e1b4c491dc7d8eacea139a1b0b295f74e1a1a0f704c375028f8320d16e31"}, - {file = "scipy-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a04cd7d0d3eff6ea4719371cbc44df31411862b9646db617c99718ff68d4840"}, - {file = "scipy-1.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:545c83ffb518094d8c9d83cce216c0c32f8c04aaf28b92cc8283eda0685162d5"}, - {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d54222d7a3ba6022fdf5773931b5d7c56efe41ede7f7128c7b1637700409108"}, - {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff3a5295234037e39500d35316a4c5794739433528310e117b8a9a0c76d20fc"}, - {file = "scipy-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:2318bef588acc7a574f5bfdff9c172d0b1bf2c8143d9582e05f878e580a3781e"}, - {file = "scipy-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d644a64e174c16cb4b2e41dfea6af722053e83d066da7343f333a54dae9bc31c"}, - {file = "scipy-1.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da8245491d73ed0a994ed9c2e380fd058ce2fa8a18da204681f2fe1f57f98f95"}, - {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db5b30849606a95dcf519763dd3ab6fe9bd91df49eba517359e450a7d80ce2e"}, - {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c68db6b290cbd4049012990d7fe71a2abd9ffbe82c0056ebe0f01df8be5436b0"}, - {file = "scipy-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:5b88e6d91ad9d59478fafe92a7c757d00c59e3bdc3331be8ada76a4f8d683f58"}, - {file = "scipy-1.9.3.tar.gz", hash = "sha256:fbc5c05c85c1a02be77b1ff591087c83bc44579c6d2bd9fb798bb64ea5e1a027"}, + {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, + {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, + {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, + {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, + {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, + {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, + {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, + {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, + {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, + {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, + {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, ] -setuptools = [ - {file = "setuptools-67.3.1-py3-none-any.whl", hash = "sha256:23c86b4e44432bfd8899384afc08872ec166a24f48a3f99f293b0a557e6a6b5d"}, - {file = "setuptools-67.3.1.tar.gz", hash = "sha256:daec07fd848d80676694d6bf69c009d28910aeece68a38dbe88b7e1bb6dba12e"}, -] -setuptools-scm = [ - {file = "setuptools_scm-7.1.0-py3-none-any.whl", hash = "sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e"}, - {file = "setuptools_scm-7.1.0.tar.gz", hash = "sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27"}, +seaborn = [ + {file = "seaborn-0.12.2-py3-none-any.whl", hash = "sha256:ebf15355a4dba46037dfd65b7350f014ceb1f13c05e814eda2c9f5fd731afc08"}, + {file = "seaborn-0.12.2.tar.gz", hash = "sha256:374645f36509d0dcab895cba5b47daf0586f77bfe3b36c97c607db7da5be0139"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +soupsieve = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] threadpoolctl = [ - {file = "threadpoolctl-3.1.0-py3-none-any.whl", hash = "sha256:8b99adda265feb6773280df41eece7b2e6561b772d21ffd52e372f999024907b"}, - {file = "threadpoolctl-3.1.0.tar.gz", hash = "sha256:a335baacfaa4400ae1f0d8e3a58d6674d2f8828e3716bb2802c44955ad391380"}, + {file = "threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032"}, + {file = "threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, @@ -1145,15 +1535,27 @@ torchvision = [ {file = "torchvision-0.13.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b167934a5943242da7b1e59318f911d2d253feeca0d13ad5d832b58eed943401"}, {file = "torchvision-0.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:0e77706cc90462653620e336bb90daf03d7bf1b88c3a9a3037df8d111823a56e"}, ] +tqdm = [ + {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, + {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, +] typing-extensions = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, +] +unfoldNd = [ + {file = "unfoldNd-0.2.1-py3-none-any.whl", hash = "sha256:5d9a7f23e9004127486eb8c58f18025529b106ad407e6271ab57f13d910a7458"}, + {file = "unfoldNd-0.2.1.tar.gz", hash = "sha256:3d91e0e6006d1ab45702db4b36f28e6150aef11c96d46331a273efe963e5efef"}, ] urllib3 = [ - {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"}, - {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"}, + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, +] +where = [ + {file = "where-1.0.2-py2.py3-none-any.whl", hash = "sha256:66abc8edf95be7516e949d08a771f25acacff708ef481618562ab484fe5bc63e"}, + {file = "where-1.0.2.zip", hash = "sha256:325ef3a492a26189a47819f7375bc146887d39edd36fce132e86514334803fb1"}, ] zipp = [ - {file = "zipp-3.13.0-py3-none-any.whl", hash = "sha256:e8b2a36ea17df80ffe9e2c4fda3f693c3dad6df1697d3cd3af232db680950b0b"}, - {file = "zipp-3.13.0.tar.gz", hash = "sha256:23f70e964bc11a34cef175bc90ba2914e1e4545ea1e3e2f67c079671883f9cb6"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] diff --git a/pyproject.toml b/pyproject.toml index 218393406..5a7ac0bf9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,27 +1,35 @@ [tool.poetry] name = "domainlab" -version = "0.1.0" -description = "Library of Domain Generalization" -authors = ["Xudong Sun ", "Alexej Gossmann "] +version = "0.6.0" +readme = "README.md" +repository = "https://github.com/marrlab/DomainLab" +homepage = "https://marrlab.github.io/DomainLab/" +description = "Library of modular domain generalization for deep learning" +authors = ["Xudong Sun ", "Carla Feistner", "Alexej Gossmann ", "et. al."] [tool.poetry.dependencies] python = "^3.9" numpy = "^1.23.4" matplotlib = "^3.6.1" seaborn = "0.12.2" -snakemake = "7.21.0" torchmetrics = "^0.10.0" torch = "^1.12.0" torchvision = "^0.13.0" -pillow = "^6.1.0" +pillow = "^9.3.0" rich = "^13.3.1" pandas = "^1.5.1" scikit-learn = "^1.2.1" pyyaml = "^6.0" +gdown = "^4.7.1" +backpack-for-pytorch = "^1.6.0" +[tool.poetry.scripts] +domainlab = 'domainlab.cli:domainlab_cli' -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] pytest = "^6.2.5" +pytest-cov = "^4.1.0" +pytest-shell = "^0.3.2" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/requirements.txt b/requirements.txt index 3209f9150..88c294a6e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,36 +1,45 @@ -certifi==2022.12.7 ; python_version >= "3.8" and python_version < "4" -charset-normalizer==3.0.1 ; python_version >= "3.8" and python_version < "4" -contourpy==1.0.7 ; python_version >= "3.8" and python_version < "4.0" -cycler==0.11.0 ; python_version >= "3.8" and python_version < "4.0" -fonttools==4.38.0 ; python_version >= "3.8" and python_version < "4.0" -idna==3.4 ; python_version >= "3.8" and python_version < "4" -joblib==1.2.0 ; python_version >= "3.8" and python_version < "4.0" -kiwisolver==1.4.4 ; python_version >= "3.8" and python_version < "4.0" -markdown-it-py==2.1.0 ; python_version >= "3.8" and python_version < "4.0" -matplotlib==3.6.3 ; python_version >= "3.8" and python_version < "4.0" -mdurl==0.1.2 ; python_version >= "3.8" and python_version < "4.0" -numpy==1.24.1 ; python_version < "4.0" and python_version >= "3.8" -packaging==23.0 ; python_version >= "3.8" and python_version < "4.0" -pandas==1.5.3 ; python_version >= "3.8" and python_version < "4.0" -pillow==6.2.2 ; python_version >= "3.8" and python_version < "4.0" -pygments==2.14.0 ; python_version >= "3.8" and python_version < "4.0" -pyparsing==3.0.9 ; python_version >= "3.8" and python_version < "4.0" -python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "4.0" -pytz==2022.7.1 ; python_version >= "3.8" and python_version < "4.0" -pyyaml==6.0 ; python_version >= "3.8" and python_version < "4.0" -requests==2.28.2 ; python_version >= "3.8" and python_version < "4" -rich==13.3.1 ; python_version >= "3.8" and python_version < "4.0" -scikit-learn==1.2.1 ; python_version >= "3.8" and python_version < "4.0" -scipy==1.9.3 ; python_version >= "3.8" and python_version < "4.0" -seaborn==0.12.2 ; python_version >= "3.8" and python_version < "4.0" -setuptools-scm==7.1.0 ; python_version >= "3.8" and python_version < "4.0" -setuptools==67.1.0 ; python_version >= "3.8" and python_version < "4.0" -snakemake==7.21.0 ; python_version >= "3.8" and python_version < "4.0" -six==1.16.0 ; python_version >= "3.8" and python_version < "4.0" -threadpoolctl==3.1.0 ; python_version >= "3.8" and python_version < "4.0" -tomli==2.0.1 ; python_version >= "3.8" and python_version < "3.11" -torch==1.12.1 ; python_version >= "3.8" and python_version < "4.0" -torchmetrics==0.10.3 ; python_version >= "3.8" and python_version < "4.0" -torchvision==0.13.1 ; python_version >= "3.8" and python_version < "4.0" -typing-extensions==4.4.0 ; python_version >= "3.8" and python_version < "4.0" -urllib3==1.26.14 ; python_version >= "3.8" and python_version < "4" +backpack-for-pytorch==1.6.0 ; python_version >= "3.9" and python_version < "4.0" +beautifulsoup4==4.12.3 ; python_version >= "3.9" and python_version < "4.0" +certifi==2023.11.17 ; python_version >= "3.9" and python_version < "4.0" +charset-normalizer==3.3.2 ; python_version >= "3.9" and python_version < "4.0" +colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and platform_system == "Windows" +contourpy==1.2.0 ; python_version >= "3.9" and python_version < "4.0" +cycler==0.12.1 ; python_version >= "3.9" and python_version < "4.0" +einops==0.7.0 ; python_version >= "3.9" and python_version < "4.0" +filelock==3.13.1 ; python_version >= "3.9" and python_version < "4.0" +fonttools==4.47.2 ; python_version >= "3.9" and python_version < "4.0" +gdown==4.7.3 ; python_version >= "3.9" and python_version < "4.0" +idna==3.6 ; python_version >= "3.9" and python_version < "4.0" +importlib-resources==6.1.1 ; python_version >= "3.9" and python_version < "3.10" +joblib==1.3.2 ; python_version >= "3.9" and python_version < "4.0" +kiwisolver==1.4.5 ; python_version >= "3.9" and python_version < "4.0" +markdown-it-py==3.0.0 ; python_version >= "3.9" and python_version < "4.0" +matplotlib==3.8.2 ; python_version >= "3.9" and python_version < "4.0" +mdurl==0.1.2 ; python_version >= "3.9" and python_version < "4.0" +numpy==1.26.3 ; python_version < "4.0" and python_version >= "3.9" +packaging==23.2 ; python_version >= "3.9" and python_version < "4.0" +pandas==1.5.3 ; python_version >= "3.9" and python_version < "4.0" +pillow==9.5.0 ; python_version >= "3.9" and python_version < "4.0" +pygments==2.17.2 ; python_version >= "3.9" and python_version < "4.0" +pyparsing==3.1.1 ; python_version >= "3.9" and python_version < "4.0" +pysocks==1.7.1 ; python_version >= "3.9" and python_version < "4.0" +python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "4.0" +pytz==2023.4 ; python_version >= "3.9" and python_version < "4.0" +pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4.0" +requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0" +requests[socks]==2.31.0 ; python_version >= "3.9" and python_version < "4.0" +rich==13.7.0 ; python_version >= "3.9" and python_version < "4.0" +scikit-learn==1.4.0 ; python_version >= "3.9" and python_version < "4.0" +scipy==1.12.0 ; python_version >= "3.9" and python_version < "4.0" +seaborn==0.12.2 ; python_version >= "3.9" and python_version < "4.0" +six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" +soupsieve==2.5 ; python_version >= "3.9" and python_version < "4.0" +threadpoolctl==3.2.0 ; python_version >= "3.9" and python_version < "4.0" +torch==1.12.1 ; python_version >= "3.9" and python_version < "4.0" +torchmetrics==0.10.3 ; python_version >= "3.9" and python_version < "4.0" +torchvision==0.13.1 ; python_version >= "3.9" and python_version < "4.0" +tqdm==4.66.1 ; python_version >= "3.9" and python_version < "4.0" +typing-extensions==4.9.0 ; python_version >= "3.9" and python_version < "4.0" +unfoldnd==0.2.1 ; python_version >= "3.9" and python_version < "4.0" +urllib3==2.1.0 ; python_version >= "3.9" and python_version < "4.0" +zipp==3.17.0 ; python_version >= "3.9" and python_version < "3.10" diff --git a/run_benchmark_slurm.sh b/run_benchmark_slurm.sh new file mode 100755 index 000000000..61615198a --- /dev/null +++ b/run_benchmark_slurm.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +timestamp() { +# date +"%T" # current time + date +"%Y-%m-%d_%H-%M-%S" +} + +# CONFIGFILE="examples/yaml/test_helm_benchmark.yaml" +CONFIGFILE=$1 +export DOMAINLAB_CUDA_START_SEED=$2 + +if [ -z "$2" ] +then + echo "argument 2: DOMAINLAB_CUDA_START_SEED empty, will set to 0" + export DOMAINLAB_CUDA_START_SEED=0 + # in fact, the smk code will hash empty string to zero, see standalone script, + # but here we just want to ensure the seed is 0 without worrying a different + # behavior of the hash function +else + export DOMAINLAB_CUDA_START_SEED=$2 +fi + + +# ensure all runs sample the same hyperparameters +export DOMAINLAB_CUDA_HYPERPARAM_SEED=0 + +export NUMBER_GPUS=1 +logdir="zoutput/logs" +mkdir -p $logdir +logfile="$logdir/$(timestamp).out" +echo "Configuration file: $CONFIGFILE" +echo "starting seed is: $DOMAINLAB_CUDA_START_SEED" +echo "verbose log: $logfile" +# Helmholtz +snakemake --profile "examples/yaml/slurm" --config yaml_file=$CONFIGFILE --keep-going --keep-incomplete --notemp --cores 3 -s "domainlab/exp_protocol/benchmark.smk" --configfile "$CONFIGFILE" 2>&1 | tee "$logfile" diff --git a/run_benchmark_standalone.sh b/run_benchmark_standalone.sh new file mode 100755 index 000000000..8f712d1d1 --- /dev/null +++ b/run_benchmark_standalone.sh @@ -0,0 +1,96 @@ +set -e + +timestamp() { +# date +"%T" # current time + date +"%Y-%m-%d_%H-%M-%S" +} + + +logdir="zoutput/logs" +mkdir -p $logdir +logfile="$logdir/$(timestamp).out" +echo "verbose log: $logfile" + + +CONFIGFILE=$1 + + + +echo "argument 2=$2" +if [ -z "$2" ] +then + echo "argument 2: DOMAINLAB_CUDA_START_SEED empty" + echo "empty string will be hashed into 0" +fi + +export DOMAINLAB_CUDA_START_SEED=$2 + + +echo "argument 3: $3" + +if [ -z "$3" ] +then + echo "argument 3: DOMAINLAB_CUDA_HYPERPARAM_SEED empty, will set to 0" + export DOMAINLAB_CUDA_HYPERPARAM_SEED=0 +else + export DOMAINLAB_CUDA_HYPERPARAM_SEED=$3 +fi + + +echo "argument 4: NUMBER_GPUS=$4" +if [ -z "$4" ] +then + export NUMBER_GPUS=1 + echo "argument 4: NUMBER_GPUS set to 1" + echo "argument 4: NUMBER_GPUS=$NUMBER_GPUS" +else + export NUMBER_GPUS=$4 +fi + + +# -n: dry-run (A dry run is a software testing process where the effects of a possible failure are intentionally mitigated, For example, there is rsync utility for transfer data over some interface, but user can try rsync with dry-run option to check syntax and test communication without data transferring.) +# -p: print shell commands +# -d: specify working directory. This should be the DomainLab dir +# -s: snakefile +# -- configfile: configuration yaml file of the benchmark + + + + +# first display all tasks +snakemake --rerun-incomplete --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "$CONFIGFILE" --keep-going --summary # this will give us a clue first what jobs will be run + +# second submit the jobs, make sure you have more than 4 cores on your laptop, otherwise adjust the cores +snakemake --config yaml_file=$CONFIGFILE --rerun-incomplete --resources nvidia_gpu=$NUMBER_GPUS --cores 4 -s "domainlab/exp_protocol/benchmark.smk" --configfile "$CONFIGFILE" 2>&1 | tee "$logfile" + + +# snakemake --rerun-incomplete --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" +# snakemake -np -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" + + +# print execution graph to pdf + +# snakemake --dag --forceall -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" | dot -Tpdf > dag.pdf + +# snakemake --rulegraph --forceall -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" | dot -Tpdf > rulegraph.pdf + +# Command used to run in the DENBI cluster +# snakemake --keep-going --keep-incomplete --notemp --cores 5 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/helm_runtime_evaluation.yaml" 2>&1 | tee $logfile + +# Command used to run in the Helmholtz cluster +# snakemake --profile "examples/yaml/slurm" --keep-going --keep-incomplete --notemp --cores 5 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/test_helm_benchmark.yaml" 2>&1 | tee "$logfile" + +# Command used to run snakemake on a demo benchmark +# snakemake -np -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" + +# First display all tasks +# snakemake --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" --keep-going --summary # this will give us a clue first what jobs will be run + +# second submit the jobs +# snakemake --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" --keep-going 2>&1 | tee "$logfile" + +# snakemake --rerun-incomplete --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" + +# only plot +# snakemake --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" --keep-going --allowed-rules agg_partial_results +# snakemake --cores 1 -s "domainlab/exp_protocol/benchmark.smk" --configfile "examples/yaml/demo_benchmark.yaml" --keep-going --allowed-rules gen_plots diff --git a/sbatch4submit_slurm_cpu_10days.sh b/sbatch4submit_slurm_cpu_10days.sh new file mode 100755 index 000000000..1b59514ae --- /dev/null +++ b/sbatch4submit_slurm_cpu_10days.sh @@ -0,0 +1,32 @@ +# change the following two lines if needed +VENV="domainlab_py39" +BASHRC="~/.bashrc" # source ~/.bash_profile + +## +JOB_NAME="submit10d" +PATH_CODE=$1 +PATH_OUT_BASE="${PATH_CODE}/job_logs" +mkdir -p $PATH_OUT_BASE +PATH_YAML=$2 +START_SEED=$3 + + +job_file="${PATH_OUT_BASE}/${JOB_NAME}.cmd" +echo "#!/bin/bash +#SBATCH -J ${JOB_NAME} +#SBATCH -o ${PATH_OUT_BASE}/${JOB_NAME}.out +#SBATCH -e ${PATH_OUT_BASE}/${JOB_NAME}.err +#SBATCH -p cpu_p +#SBATCH -t 10-00:00:00 +#SBATCH -c 20 +#SBATCH --mem=32G +#SBATCH --qos=cpu_long +#SBATCH --no-requeue +#SBATCH --nice=10000 + +source ${BASHRC} +conda activate ${VENV} + +${PATH_CODE}/run_benchmark_slurm.sh ${PATH_CODE}/${PATH_YAML} ${START_SEED} +" > ${job_file} +sbatch ${job_file} diff --git a/sbatch4submit_slurm_cpu_3days.sh b/sbatch4submit_slurm_cpu_3days.sh new file mode 100755 index 000000000..2c827eef7 --- /dev/null +++ b/sbatch4submit_slurm_cpu_3days.sh @@ -0,0 +1,37 @@ +# change the following two lines if needed +VENV="domainlab_py39" +BASHRC="~/.bashrc" # source ~/.bash_profile + +## +JOB_NAME="submit" +PATH_CODE=$1 +PATH_OUT_BASE="${PATH_CODE}/submit_job_logs" +mkdir -p $PATH_OUT_BASE +PATH_YAML=$2 +START_SEED=$3 +ACTIVE_TIME="3-00:00:00" + +job_file="${PATH_OUT_BASE}/${JOB_NAME}.cmd" + + +# echo the following line to ${job_file} +echo "#!/bin/bash +#SBATCH -J ${JOB_NAME} +#SBATCH -o ${PATH_OUT_BASE}/${JOB_NAME}.out +#SBATCH -e ${PATH_OUT_BASE}/${JOB_NAME}.err +#SBATCH -p cpu_p +#SBATCH -t ${ACTIVE_TIME} +#SBATCH -c 20 +#SBATCH --mem=32G +#SBATCH --qos=cpu_normal +#SBATCH --no-requeue +#SBATCH --nice=10000 + +source ${BASHRC} +conda activate ${VENV} + +${PATH_CODE}/run_benchmark_slurm.sh ${PATH_CODE}/${PATH_YAML} ${START_SEED} +" > ${job_file} +# end of echo + +sbatch ${job_file} diff --git a/contri.sh b/scripts/contri.sh similarity index 100% rename from contri.sh rename to scripts/contri.sh diff --git a/sh_add_dependencies.sh b/scripts/sh_add_dependencies.sh similarity index 85% rename from sh_add_dependencies.sh rename to scripts/sh_add_dependencies.sh index e2a9b50f1..a4ad51938 100644 --- a/sh_add_dependencies.sh +++ b/scripts/sh_add_dependencies.sh @@ -1,3 +1,4 @@ +#!/bin/bash -x -v poetry add $1 poetry update poetry export -f requirements.txt --output requirements.txt --without-hashes diff --git a/scripts/sh_design.sh b/scripts/sh_design.sh new file mode 100644 index 000000000..d0c8e2105 --- /dev/null +++ b/scripts/sh_design.sh @@ -0,0 +1,4 @@ +#!/bin/bash -x -v +# sudo apt-get install librsvg2-bin +java -jar ~/opt/plantuml.jar domainlab/uml/libDG.uml -tsvg +rsvg-convert -f pdf -o DomainLab.pdf domainlab/uml/libDG.svg diff --git a/scripts/sh_gen_requirements.sh b/scripts/sh_gen_requirements.sh new file mode 100644 index 000000000..ca0bd55a1 --- /dev/null +++ b/scripts/sh_gen_requirements.sh @@ -0,0 +1,6 @@ +#!/bin/bash +poetry update +poetry export -f requirements.txt --output requirements.txt --without-hashes --without-urls +# without snakemake and datrie +# poetry export -f requirements.txt --output requirements.txt --without-hashes --without-urls --without snakemake diatrie +# only snamkemake poetry export --without-hashes -f requirements.txt | grep -v colorama > requirements.txt diff --git a/scripts/sh_genplot.sh b/scripts/sh_genplot.sh new file mode 100644 index 000000000..a1b1ecfad --- /dev/null +++ b/scripts/sh_genplot.sh @@ -0,0 +1,2 @@ +mkdir $2 +python main_out.py --gen_plots $1 --outp_dir $2 diff --git a/scripts/sh_link_pacs_dataset.sh b/scripts/sh_link_pacs_dataset.sh new file mode 100644 index 000000000..742f256e5 --- /dev/null +++ b/scripts/sh_link_pacs_dataset.sh @@ -0,0 +1,2 @@ +mkdir -p data/pacs +ln -s ~/Documents/datasets/pacs/raw data/pacs/PACS diff --git a/sh_gen_requirements.sh b/scripts/sh_update_requirements.sh similarity index 58% rename from sh_gen_requirements.sh rename to scripts/sh_update_requirements.sh index a1feef26d..9974dc543 100644 --- a/sh_gen_requirements.sh +++ b/scripts/sh_update_requirements.sh @@ -1,2 +1,3 @@ -#!/bin/bash -poetry export -f requirements.txt --output requirements.txt --without-hashes --without-urls +#!/bin/bash -x -v +poetry update +poetry export -f requirements.txt --output requirements.txt --without-hashes diff --git a/setup.py b/setup.py index f4cb4be64..74680c5b1 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,46 @@ +""" +run python setup.py install to install DomainLab into system +""" +import os + from setuptools import find_packages, setup + + +def copy_dir(dir_path="zdata"): + # root = os.path.dirname(os.path.abspath(__file__)) + root = os.path.normpath(".") + base_dir = os.path.join(root, "domainlab", dir_path) + for dirpath, dirnames, files in os.walk(base_dir): + for f in files: + path = os.path.join(dirpath.split("/", 1)[1], f) + print(path) + yield path + + setup( - name='domainlab', + name="domainlab", packages=find_packages(), - version='0.1.0', - description='Library of Domain Generalization', - author='Xudong Sun, et.al.', - license='', + # include_package_data=True, + # data_files=[ + # ('bitmaps', ['bm/b1.gif', 'bm/b2.gif']), + # ('/opt/local/myproject/etc', ['myproject/config/settings.py', 'myproject/config/other_settings.special']), + # ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'cool.huh')]), + # + # ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'other_settings.xml')]), + # ('/opt/local/myproject/data', [os.path.join('myproject/words', 'word_set.txt')]), + # ], + # data_files = [ + # ('../data', 'data/*') + # ], + # data_files = [ + # ('../data', f) for f in copy_dir() + # ], + package_data={ + "zdata": [f for f in copy_dir()], + }, + version="0.6.0", + description="Library of modular domain generalization for deep learning", + url="https://github.com/marrlab/DomainLab", + author="Xudong Sun, et.al.", + license="MIT", ) diff --git a/setup_install.sh b/setup_install.sh index 0649d567d..52afd955b 100644 --- a/setup_install.sh +++ b/setup_install.sh @@ -1,3 +1,14 @@ +# source distribution +python setup.py sdist +pip install -e . #!/bin/bash python setup.py develop -# python setup.py bdist_wheel +echo "=================================" +python setup.py install --record installed_files.txt + +cat installed_files.txt +xargs rm -rf < install_files.txt + +echo "===========wheel======================" + +python setup.py bdist_wheel diff --git a/sh_benchmark_agg.sh b/sh_benchmark_agg.sh new file mode 100644 index 000000000..f9997e705 --- /dev/null +++ b/sh_benchmark_agg.sh @@ -0,0 +1,3 @@ +cat $1/rule_results/*.csv > temp_results.csv +mkdir -p temp_agg +python main_out.py --gen_plots temp_results.csv --outp_dir ./temp_agg diff --git a/sh_download_pacs.sh b/sh_download_pacs.sh new file mode 100644 index 000000000..e6b8b2020 --- /dev/null +++ b/sh_download_pacs.sh @@ -0,0 +1,3 @@ +mkdir -p data/pacs +cd data/script +python download_pacs.py diff --git a/sh_list_error.sh b/sh_list_error.sh new file mode 100644 index 000000000..5f725e15b --- /dev/null +++ b/sh_list_error.sh @@ -0,0 +1,5 @@ +# find $1 -type f -print0 | xargs -0 grep -li error +# B means before, A means after, some erros have long stack exception message so we need at least +# 100 lines before the error, the last line usually indicate the root cause of error +grep -B 100 -wnr "error" --group-separator="=========begin_slurm_error===============" $1 > slurm_errors.txt +cat slurm_errors.txt diff --git a/sh_list_job_via_slurm_id.sh b/sh_list_job_via_slurm_id.sh new file mode 100644 index 000000000..d8e2272ce --- /dev/null +++ b/sh_list_job_via_slurm_id.sh @@ -0,0 +1 @@ +find zoutput/slurm_logs/run_experiment/ | grep -i "$1" diff --git a/sh_publish.sh b/sh_publish.sh index d360547b6..cd07b36fa 100644 --- a/sh_publish.sh +++ b/sh_publish.sh @@ -1,2 +1,6 @@ -poetry config pypi-token.pypi [my-token] -poetry publish +#!/bin/bash -x -v +# step 1: in case for a new download of the repository, get the token via https://pypi.org/manage/project/domainlab/settings/, then do +# poetry config pypi-token.pypi [my-token] +# step 2: change the version in pyproject.toml +poetry build # step 3 +poetry publish # step 4 diff --git a/submit_slurm_via_cpu_10days.sh b/submit_slurm_via_cpu_10days.sh new file mode 100644 index 000000000..eada249b4 --- /dev/null +++ b/submit_slurm_via_cpu_10days.sh @@ -0,0 +1,4 @@ +rm -f -R .snakemake +DIR=$(pwd) +echo $DIR +bash ./sbatch4submit_slurm_cpu_10days.sh $DIR $1 $2 diff --git a/submit_slurm_via_cpu_3days.sh b/submit_slurm_via_cpu_3days.sh new file mode 100644 index 000000000..adff5e0a5 --- /dev/null +++ b/submit_slurm_via_cpu_3days.sh @@ -0,0 +1,4 @@ +rm -f -R .snakemake +DIR=$(pwd) +echo $DIR +bash ./sbatch4submit_slurm_cpu_3days.sh $DIR $1 $2 diff --git a/tests/__init__.py b/tests/__init__.py index ee34bf5e0..31c61ca83 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1 @@ -"""Unit tests for DomainLab""" \ No newline at end of file +"""Unit tests for DomainLab""" diff --git a/tests/dset_mnist_color_solo_default_test.py b/tests/dset_mnist_color_solo_default_test.py index a7be9c65e..76e32bfdb 100644 --- a/tests/dset_mnist_color_solo_default_test.py +++ b/tests/dset_mnist_color_solo_default_test.py @@ -25,22 +25,24 @@ def test_color_mnist2(): ds_list.append(DsetMNISTColorSoloDefault(i, "zout")) plot_ds_list(ds_list, "zout/color_0_9.png") + def test_color_mnist3(): """ test_color_mnist """ - dset = DsetMNISTColorSoloDefault(0, "zout", color_scheme="num", raw_split='test') + dset = DsetMNISTColorSoloDefault(0, "zout", color_scheme="num", raw_split="test") plot_ds(dset, "zout/color_solo.png") ds_list = [] for i in range(10): ds_list.append(DsetMNISTColorSoloDefault(i, "zout")) plot_ds_list(ds_list, "zout/color_0_9.png") + def test_color_mnist4(): """ test_color_mnist """ - dset = DsetMNISTColorSoloDefault(0, "zout", color_scheme="back", raw_split='test') + dset = DsetMNISTColorSoloDefault(0, "zout", color_scheme="back", raw_split="test") plot_ds(dset, "zout/color_solo.png") ds_list = [] for i in range(10): diff --git a/tests/dset_poly_domains_mnist_color_default_test.py b/tests/dset_poly_domains_mnist_color_default_test.py index 1847f9df4..1e0661eca 100644 --- a/tests/dset_poly_domains_mnist_color_default_test.py +++ b/tests/dset_poly_domains_mnist_color_default_test.py @@ -2,8 +2,9 @@ merge several solo-color mnist to form a mixed dataset """ -from domainlab.dsets.utils_data import plot_ds from domainlab.dsets.dset_poly_domains_mnist_color_default import DsetMNISTColorMix +from domainlab.dsets.utils_data import plot_ds + def test_color_mnist(): dset = DsetMNISTColorMix(n_domains=3, path="./output/") diff --git a/tests/dset_subfolder_test.py b/tests/dset_subfolder_test.py index d7ded4adc..ccf9bc575 100644 --- a/tests/dset_subfolder_test.py +++ b/tests/dset_subfolder_test.py @@ -4,55 +4,66 @@ """ import pytest -from domainlab.dsets.utils_data import fun_img_path_loader_default from domainlab.dsets.dset_subfolder import DsetSubFolder +from domainlab.dsets.utils_data import fun_img_path_loader_default def test_fun(): - dset = DsetSubFolder(root="data/vlcs_mini/caltech", - list_class_dir=["auto", "vogel"], - loader=fun_img_path_loader_default, - extensions="jpg", - transform=None, - target_transform=None) + dset = DsetSubFolder( + root="data/vlcs_mini/caltech", + list_class_dir=["auto", "vogel"], + loader=fun_img_path_loader_default, + extensions="jpg", + transform=None, + target_transform=None, + ) dset.class_to_idx def test_mixed_codec(): """Check if only images with given extension are loaded.""" - dset = DsetSubFolder(root="data/mixed_codec/caltech", - list_class_dir=["auto", "vogel"], - loader=fun_img_path_loader_default, - extensions=None, - transform=None, - target_transform=None) + dset = DsetSubFolder( + root="data/mixed_codec/caltech", + list_class_dir=["auto", "vogel"], + loader=fun_img_path_loader_default, + extensions=None, + transform=None, + target_transform=None, + ) assert len(dset.samples) == 6 - dset = DsetSubFolder(root="data/mixed_codec/caltech", - list_class_dir=["auto", "vogel"], - loader=fun_img_path_loader_default, - extensions="jpg", - transform=None, - target_transform=None) - assert len(dset.samples) == 4,\ - f"data/mixed_codec contains 4 jpg files, but {len(dset.samples)} were loaded." + dset = DsetSubFolder( + root="data/mixed_codec/caltech", + list_class_dir=["auto", "vogel"], + loader=fun_img_path_loader_default, + extensions="jpg", + transform=None, + target_transform=None, + ) + assert ( + len(dset.samples) == 4 + ), f"data/mixed_codec contains 4 jpg files, but {len(dset.samples)} were loaded." with pytest.raises(ValueError): - DsetSubFolder(root="data/mixed_codec/caltech", - list_class_dir=["auto", "vogel"], - loader=fun_img_path_loader_default, - extensions="jpg", - transform=None, - target_transform=None, - is_valid_file=True) + DsetSubFolder( + root="data/mixed_codec/caltech", + list_class_dir=["auto", "vogel"], + loader=fun_img_path_loader_default, + extensions="jpg", + transform=None, + target_transform=None, + is_valid_file=True, + ) def test_wrong_class_names(): """Check for error if list_class_dir does not match the subfolders.""" with pytest.raises(RuntimeError): - DsetSubFolder(root="data/mixed_codec/caltech", - list_class_dir=["auto", "haus"], - loader=fun_img_path_loader_default, - extensions=None, - transform=None, - target_transform=None) + DsetSubFolder( + root="data/mixed_codec/caltech", + list_class_dir=["auto", "haus"], + loader=fun_img_path_loader_default, + extensions=None, + transform=None, + target_transform=None, + ) diff --git a/tests/dset_utils_data_test.py b/tests/dset_utils_data_test.py index 1e2beac73..3b618146c 100644 --- a/tests/dset_utils_data_test.py +++ b/tests/dset_utils_data_test.py @@ -3,7 +3,7 @@ def test_dset_in_mem_decorator(): - dset = DsetMNISTColorSoloDefault(path ="../data", ind_color=1) + dset = DsetMNISTColorSoloDefault(path="../data", ind_color=1) dset_in_memory = DsetInMemDecorator(dset=dset) dset_in_memory.__len__() - dset_in_memory.__getitem__(0) \ No newline at end of file + dset_in_memory.__getitem__(0) diff --git a/tests/test_argparse.py b/tests/test_argparse.py index e0e9be5c9..683f66911 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -2,45 +2,55 @@ Test argparser functionality """ -import sys import os +import sys + import pytest -from domainlab.arg_parser import parse_cmd_args + +from domainlab.arg_parser import apply_dict_to_args, mk_parser_main, parse_cmd_args def test_parse_cmd_args_warning(): - """Call argparser for command line - """ - sys.argv = ['main.py'] - with pytest.warns(Warning, match='no algorithm conf specified'): + """Call argparser for command line""" + sys.argv = ["main.py"] + with pytest.warns(Warning, match="no algorithm conf specified"): parse_cmd_args() def test_parse_yml_args(): - """Test argparser with yaml file - """ + """Test argparser with yaml file""" testdir = os.path.dirname(os.path.realpath(__file__)) rootdir = os.path.join(testdir, "..") rootdir = os.path.abspath(rootdir) - file_path = os.path.join(rootdir, "examples/yaml/demo.yaml") - sys.argv = ['main.py', '--config=' + file_path] + file_path = os.path.join(rootdir, "examples/yaml/demo_config_single_run_diva.yaml") + sys.argv = ["main.py", "--config=" + file_path] args = parse_cmd_args() # Checking if arguments are from demo.yaml assert args.te_d == "caltech" assert args.tpath == "examples/tasks/task_vlcs.py" assert args.bs == 2 - assert args.aname == "diva" + assert args.model == "diva" assert args.gamma_y == 700000.0 + def test_parse_invalid_yml_args(): - """Test argparser with yaml file - """ + """Test argparser with yaml file""" testdir = os.path.dirname(os.path.realpath(__file__)) rootdir = os.path.join(testdir, "..") rootdir = os.path.abspath(rootdir) file_path = os.path.join(rootdir, "examples/yaml/demo_invalid_parameter.yaml") - sys.argv = ['main.py', '--config=' + file_path] - + sys.argv = ["main.py", "--config=" + file_path] + with pytest.raises(ValueError): parse_cmd_args() + + +def test_apply_dict_to_args(): + """Testing apply_dict_to_args""" + parser = mk_parser_main() + args = parser.parse_args(args=[]) + data = {"a": 1, "b": [1, 2], "model": "diva"} + apply_dict_to_args(args, data, extend=True) + assert args.a == 1 + assert args.model == "diva" diff --git a/tests/test_benchmark_plots.py b/tests/test_benchmark_plots.py index 9849fa302..f8018dd5f 100644 --- a/tests/test_benchmark_plots.py +++ b/tests/test_benchmark_plots.py @@ -1,14 +1,18 @@ -''' +""" Test the benchmark plots using some dummy results saved in .csv files -''' +""" from domainlab.utils.generate_benchmark_plots import gen_benchmark_plots def test_benchm_plots(): - ''' + """ test benchmark plots - ''' - gen_benchmark_plots('data/ztest_files/aggret_res_test1', - 'zoutput/benchmark_plots_test/outp1') - gen_benchmark_plots('data/ztest_files/aggret_res_test2', - 'zoutput/benchmark_plots_test/outp2') + """ + gen_benchmark_plots( + "data/ztest_files/aggret_res_test1", + "zoutput/benchmark_plots_test/outp1", + use_param_index=False, + ) + gen_benchmark_plots( + "data/ztest_files/aggret_res_test2", "zoutput/benchmark_plots_test/outp2" + ) diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 000000000..9d4d738e3 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,52 @@ +""" +test 'domainlab' entry point +""" + +from importlib.metadata import entry_points + +from domainlab.cli import domainlab_cli + + +def test_entry_point(): + """ + Test the entry point for the 'domainlab' console script. + + This function retrieves all entry points and asserts that the 'domainlab' + entry point is correctly associated with the 'domainlab_cli' function. + """ + eps = entry_points() + cli_entry = eps.select(group="console_scripts")["domainlab"] + assert cli_entry.load() is domainlab_cli + + +def test_domainlab_cli(monkeypatch): + """ + Test the 'domainlab_cli' function by simulating command-line arguments. + + This function uses the 'monkeypatch' fixture to set the command-line + arguments for the 'domainlab_cli' function and then calls it to ensure + it processes the arguments correctly. The test arguments simulate a + representative command-line input for the 'domainlab' tool. + """ + test_args = [ + "--te_d", + "1", + "2", + "--tr_d", + "0", + "3", + "--task", + "mnistcolor10", + "--epos", + "500", + "--bs", + "16", + "--model", + "erm", + "--nname", + "conv_bn_pool_2", + "--lr", + "1e-3", + ] + monkeypatch.setattr("sys.argv", ["domainlab"] + test_args) + domainlab_cli() diff --git a/tests/test_custom_algo.py b/tests/test_custom_model.py similarity index 52% rename from tests/test_custom_algo.py rename to tests/test_custom_model.py index 3cffa6f47..507729fc3 100644 --- a/tests/test_custom_algo.py +++ b/tests/test_custom_model.py @@ -1,21 +1,26 @@ +import gc import os + import pytest import torch -import gc -from domainlab.compos.exp.exp_main import Exp -from domainlab.models.model_custom import AModelCustom + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp +from domainlab.models.model_custom import AModelCustom def test_custom(): testdir = os.path.dirname(os.path.realpath(__file__)) rootdir = os.path.join(testdir, "..") rootdir = os.path.abspath(rootdir) - mpath = os.path.join(rootdir, "examples/algos/demo_custom_model.py") + mpath = os.path.join(rootdir, "examples/models/demo_custom_model.py") parser = mk_parser_main() - argsstr = "--te_d=caltech --task=mini_vlcs --aname=custom --bs=2 --debug \ + argsstr = ( + "--te_d=caltech --task=mini_vlcs --model=custom --bs=2 --debug \ --apath=%s --nname_argna2val my_custom_arg_name \ - --nname_argna2val alexnet" % (mpath) + --nname_argna2val alexnet --nname=alexnet" + % (mpath) + ) margs = parser.parse_args(argsstr.split()) exp = Exp(margs) exp.trainer.before_tr() @@ -30,12 +35,15 @@ def test_custom2(): testdir = os.path.dirname(os.path.realpath(__file__)) rootdir = os.path.join(testdir, "..") rootdir = os.path.abspath(rootdir) - mpath = os.path.join(rootdir, "examples/algos/demo_custom_model.py") + mpath = os.path.join(rootdir, "examples/models/demo_custom_model.py") path_net = os.path.join(rootdir, "examples/nets/resnet.py") parser = mk_parser_main() - argsstr = "--te_d=caltech --task=mini_vlcs --aname=custom --bs=2 --debug \ + argsstr = ( + "--te_d=caltech --task=mini_vlcs --model=custom --bs=2 --debug \ --apath=%s --npath_argna2val my_custom_arg_name \ - --npath_argna2val %s" % (mpath, path_net) + --npath_argna2val %s" + % (mpath, path_net) + ) margs = parser.parse_args(argsstr.split()) exp = Exp(margs) exp.trainer.before_tr() @@ -46,24 +54,14 @@ def test_custom2(): gc.collect() -def test_amodelcustom(): - """Test that AModelCustom raises correct NotImplementedErrors +def test_no_network_exeption(): """ - class Custom(AModelCustom): - """Dummy class to create an instance of the abstract AModelCustom - """ - @property - def dict_net_module_na2arg_na(self): - pass - - mod = Custom(None) - with pytest.raises(NotImplementedError): - mod.cal_logit_y(None) - with pytest.raises(NotImplementedError): - mod.forward(None, None, None) - with pytest.raises(NotImplementedError): - mod.cal_loss(None, None, None) - del mod - torch.cuda.empty_cache() - gc.collect() - + test if we can acess the exeption wen using a costum network + which is not a network + """ + parser = mk_parser_main() + argsstr = "--te_d=caltech --task=mini_vlcs --debug \ + --bs=8 --model=erm --npath=tests/this_is_not_a_network.py" + margs = parser.parse_args(argsstr.split()) + with pytest.raises(RuntimeError, match="the pytorch module returned by"): + Exp(margs) diff --git a/tests/test_dann_jigen_transformer.py b/tests/test_dann_jigen_transformer.py new file mode 100644 index 000000000..a04fe429b --- /dev/null +++ b/tests/test_dann_jigen_transformer.py @@ -0,0 +1,81 @@ +""" +DomainLab API CODING +""" + +import torch +from torch import nn +from torchvision.models import vit_b_16 +from torchvision.models.feature_extraction import create_feature_extractor + +from domainlab.mk_exp import mk_exp +from domainlab.models.model_dann import mk_dann +from domainlab.models.model_jigen import mk_jigen +from domainlab.tasks import get_task + + +class VIT(nn.Module): + """ + Vision transformer as feature extractor + """ + + def __init__( + self, freeze=True, list_str_last_layer=["getitem_5"], len_last_layer=768 + ): + super().__init__() + self.nets = vit_b_16(pretrained=True) + if freeze: + # freeze all the network except the final layer, + # for fast code execution, set freeze=False + # in case of enough computation resources + for param in self.nets.parameters(): + param.requires_grad = False + self.features_vit_flatten = create_feature_extractor( + self.nets, return_nodes=list_str_last_layer + ) + + def forward(self, tensor_x): + """ + compute logits predicts + """ + out = self.features_vit_flatten(tensor_x)["getitem_5"] + return out + + +def test_transformer(): + """ + test mk experiment API + """ + # specify domain generalization task + task = get_task("mini_vlcs") + # specify neural network to use as feature extractor + net_feature = VIT(freeze=True) + # since the size of feature is 768 + net_classifier = nn.Linear(768, task.dim_y) + + # see documentation for each arguments below + model_dann = mk_dann( + net_classifier=net_classifier, + list_str_y=task.list_str_y, + )( + net_encoder=net_feature, + net_discriminator=nn.Linear(768, 2), + list_d_tr=["labelme", "sun"], + alpha=1.0, + ) + # see documentation for each argument below + model_jigen = mk_jigen( + net_classifier=net_classifier, + list_str_y=task.list_str_y)( + net_encoder=net_feature, + net_classifier_permutation=nn.Linear(768, 32), + coeff_reg=1.0, + n_perm=31, + ) + + model_dann.extend(model_jigen) # let Jigen decorate DANN + model = model_dann + # make trainer for model, here we decorate trainer mldg with dial + exp = mk_exp( + task, model, trainer="mldg_dial", test_domain="caltech", batchsize=2, nocu=True + ) + exp.execute(num_epochs=2) diff --git a/tests/test_decorate_model.py b/tests/test_decorate_model.py new file mode 100644 index 000000000..ccf467ae2 --- /dev/null +++ b/tests/test_decorate_model.py @@ -0,0 +1,96 @@ +""" +make an experiment using "jigen" model +""" + +from torch import nn +from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights + +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.mk_exp import mk_exp +from domainlab.models.model_dann import mk_dann +from domainlab.models.model_jigen import mk_jigen +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize + + +def test_mk_exp_jigen(): + """ + test mk experiment API with "jigen" model and "mldg", "dial" trainer + """ + mk_exp_jigen(trainer="dial") + + +def mk_exp_jigen(trainer="mldg"): + """ + test mk experiment API with "jigen" model and custom trainer + """ + + # specify domain generalization task: + task = mk_task_dset(dim_y=10, isize=ImSize(3, 28, 28), taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify parameters + num_output_net_classifier = task.dim_y + num_output_net_permutation = 32 + list_str_y = [f"class{i}" for i in range(num_output_net_classifier)] + list_str_d = ["domain1", "domain2", "domain3"] + coeff_reg = 1e-3 + + # specify net encoder + net_encoder = torchvisionmodels.resnet.resnet50( + weights=ResNet50_Weights.IMAGENET1K_V2 + ) + num_output_net_encoder = net_encoder.fc.out_features + + # specify permutation classifier as linear network + net_permutation_classifier = nn.Linear( + num_output_net_encoder, num_output_net_permutation + ) + + # specify label classifier as linear network + net_classifier = nn.Linear(num_output_net_encoder, num_output_net_classifier) + + # specify model to use + model = mk_jigen( + list_str_y=list_str_y, + net_classifier=net_classifier + )( + net_encoder=net_encoder, + net_classifier_permutation=net_permutation_classifier, + coeff_reg=coeff_reg) + + num_output_net_discriminator = 2 + net_discriminator = nn.Linear(num_output_net_encoder, num_output_net_discriminator) + alpha = 0.3 + model2 = mk_dann( + list_str_y=list_str_y, + net_classifier=net_classifier + )( + ["domain2", "domain3"], + alpha, + net_encoder, + net_discriminator, + ) + + model.extend(model2) + + # make trainer for model + exp = mk_exp( + task, model, trainer=trainer, test_domain="domain1", batchsize=32, nocu=True + ) + exp.execute(num_epochs=2) diff --git a/tests/test_decorate_model_cmd.py b/tests/test_decorate_model_cmd.py new file mode 100644 index 000000000..399b90181 --- /dev/null +++ b/tests/test_decorate_model_cmd.py @@ -0,0 +1,24 @@ +""" +end to end test for trainer decorator +""" +from tests.utils_test import utils_test_algo + + +def test_cmd_model_erm_decorator_diva(): + """ + trainer decorator + """ + args = "--te_d=0 --task=mnistcolor10 --model=erm_diva\ + --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 \ + --gamma_y=10e5 --gamma_d=1e5" + utils_test_algo(args) + + +def test_cmd_model_dann_decorator_diva(): + """ + trainer decorator + """ + args = "--te_d=0 --task=mnistcolor10 --model=dann_diva\ + --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 \ + --gamma_y=10e5 --gamma_d=1e5" + utils_test_algo(args) diff --git a/tests/test_decorate_trainer.py b/tests/test_decorate_trainer.py new file mode 100644 index 000000000..a8470a9a7 --- /dev/null +++ b/tests/test_decorate_trainer.py @@ -0,0 +1,24 @@ +""" +end to end test for trainer decorator +""" +from tests.utils_test import utils_test_algo + + +def test_trainer_decorator_matchdg_dial(): + """ + trainer decorator + """ + args = "--te_d=0 --task=mnistcolor10 --model=diva \ + --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 \ + --gamma_y=10e5 --gamma_d=1e5 --trainer=matchdg_dial" + utils_test_algo(args) + + +def test_trainer_decorator_mldg_dial(): + """ + trainer decorator + """ + args = "--te_d=0 --task=mnistcolor10 --model=diva \ + --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 \ + --gamma_y=10e5 --gamma_d=1e5 --trainer=mldg_dial" + utils_test_algo(args) diff --git a/tests/test_deepalldann.py b/tests/test_deepalldann.py index c06593050..962808452 100644 --- a/tests/test_deepalldann.py +++ b/tests/test_deepalldann.py @@ -1,24 +1,35 @@ """ unit and end-end test for deep all, dann """ -import os import gc +import os + import torch -from domainlab.compos.exp.exp_main import Exp + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp from tests.utils_test import utils_test_algo -def test_deepall(): +def test_erm(): """ unit deep all """ parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "deepall", "--bs", "2", - "--nname", "conv_bn_pool_2" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "erm", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) @@ -27,7 +38,7 @@ def test_deepall(): gc.collect() -def test_deepall_res(): +def test_erm_res(): """ resnet on deep all """ @@ -37,11 +48,52 @@ def test_deepall_res(): path = os.path.join(rootdir, "examples/nets/resnet.py") parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "deepall", "--bs", "2", - "--npath", f"{path}" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "erm", + "--bs", + "2", + "--npath", + f"{path}", + ] + ) + exp = Exp(margs) + exp.trainer.before_tr() + exp.trainer.tr_epoch(0) + del exp + torch.cuda.empty_cache() + gc.collect() + + +def test_erm_resdombed(): + """ + resnet on deep all + """ + testdir = os.path.dirname(os.path.realpath(__file__)) + rootdir = os.path.join(testdir, "..") + rootdir = os.path.abspath(rootdir) + path = os.path.join(rootdir, "examples/nets/resnet50domainbed.py") + + parser = mk_parser_main() + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "erm", + "--bs", + "2", + "--npath", + f"{path}", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) @@ -55,12 +107,22 @@ def test_dann(): domain adversarial neural network """ parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "dann", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--gamma_reg", "1.0" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "dann", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + "--gamma_reg", + "1.0", + ] + ) exp = Exp(margs) exp.execute() del exp @@ -72,21 +134,32 @@ def test_dann_dial(): """ train DANN with DIAL """ - args = "--te_d=caltech --task=mini_vlcs --aname=dann --bs=2 --nname=alexnet --gamma_reg=1.0 --trainer=dial" + args = "--te_d=caltech --task=mini_vlcs --model=dann --bs=2 --nname=alexnet --gamma_reg=1.0 --trainer=dial" utils_test_algo(args) def test_sanity_check(): """Sanity check of the dataset""" parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "dann", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--gamma_reg", "1.0", - "--san_check", - "--san_num", "4" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "dann", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + "--gamma_reg", + "1.0", + "--san_check", + "--san_num", + "4", + ] + ) exp = Exp(margs) exp.execute() del exp diff --git a/tests/test_densenet.py b/tests/test_densenet.py index ff2380ffe..4b70044ac 100644 --- a/tests/test_densenet.py +++ b/tests/test_densenet.py @@ -1,13 +1,15 @@ -''' +""" Code coverage issues: https://app.codecov.io/gh/marrlab/DomainLab/blob/master/domainlab/compos/nn_zoo/net_conv_conv_bn_pool_2.py - lines 66-67, 69-71, 73 - lines 79-82 -''' +""" import gc + import torch -from domainlab.compos.nn_zoo.nn import DenseNet + from domainlab.compos.nn_zoo.net_conv_conv_bn_pool_2 import NetConvDense +from domainlab.compos.nn_zoo.nn import DenseNet def test_netconvdense1(): @@ -15,9 +17,9 @@ def test_netconvdense1(): test convdensenet """ inpu = torch.randn(1, 3, 28, 28) - model = NetConvDense(i_c=3, i_h=28, i_w=28,\ - conv_stride=1, dim_out_h=32,\ - args=None, dense_layer=None) + model = NetConvDense( + isize=(3, 28, 28), conv_stride=1, dim_out_h=32, args=None, dense_layer=None + ) model(inpu) del model torch.cuda.empty_cache() @@ -30,9 +32,13 @@ def test_netconvdense2(): """ inpu = torch.randn(1, 3, 28, 28) dense_layers = DenseNet(1024, out_hidden_size=32) - model = NetConvDense(i_c=3, i_h=28, i_w=28,\ - conv_stride=1, dim_out_h=32,\ - args=None, dense_layer=dense_layers) + model = NetConvDense( + isize=(3, 28, 28), + conv_stride=1, + dim_out_h=32, + args=None, + dense_layer=dense_layers, + ) model(inpu) del model torch.cuda.empty_cache() diff --git a/tests/test_dial.py b/tests/test_dial.py index 63ec7a1aa..5a5a770d8 100644 --- a/tests/test_dial.py +++ b/tests/test_dial.py @@ -3,9 +3,11 @@ so it is easier to identify which algorithm has a problem """ import gc + import torch -from domainlab.compos.exp.exp_main import Exp + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp def test_trainer_dial(): @@ -13,14 +15,25 @@ def test_trainer_dial(): end to end test """ parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "0", - "--task", "mnistcolor10", - "--aname", "deepall_dial", "--bs", "2", - "--nname", "conv_bn_pool_2"]) + margs = parser.parse_args( + [ + "--te_d", + "0", + "--task", + "mnistcolor10", + "--model", + "erm", + "--bs", + "2", + "--trainer", + "dial", + "--nname", + "conv_bn_pool_2", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) del exp torch.cuda.empty_cache() gc.collect() - diff --git a/tests/test_diva.py b/tests/test_diva.py index 32886221a..b53bc50e5 100644 --- a/tests/test_diva.py +++ b/tests/test_diva.py @@ -1,8 +1,10 @@ -import os import gc +import os + import torch -from domainlab.compos.exp.exp_main import Exp + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp from tests.utils_test import utils_test_algo @@ -10,13 +12,16 @@ def test_dial_diva(): """ the combination of dial and diva: use dial trainer to train diva model """ - utils_test_algo("--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=diva \ + utils_test_algo( + "--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=diva \ --nname=conv_bn_pool_2 --nname_dom=conv_bn_pool_2 \ - --gamma_y=7e5 --gamma_d=1e5 --trainer=dial") + --gamma_y=7e5 --gamma_d=1e5 --trainer=dial" + ) + def test_diva(): parser = mk_parser_main() - argsstr = "--te_d=caltech --task=mini_vlcs --aname=diva --bs=2 \ + argsstr = "--te_d=caltech --task=mini_vlcs --model=diva --bs=2 \ --nname=conv_bn_pool_2 --gamma_y=7e5 --gamma_d=7e5 \ --nname_dom=conv_bn_pool_2 --gen --nocu" margs = parser.parse_args(argsstr.split()) @@ -29,17 +34,28 @@ def test_diva(): gc.collect() - def test_trainer_diva(): parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "diva", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--gamma_y", "7e5", - "--gamma_d", "7e5", - "--nname_dom", "conv_bn_pool_2" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "diva", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + "--gamma_y", + "7e5", + "--gamma_d", + "7e5", + "--nname_dom", + "conv_bn_pool_2", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) @@ -48,21 +64,32 @@ def test_trainer_diva(): gc.collect() - def test_trainer_diva_folder(): testdir = os.path.dirname(os.path.realpath(__file__)) rootdir = os.path.join(testdir, "..") rootdir = os.path.abspath(rootdir) path = os.path.join(rootdir, "examples/tasks/task_vlcs.py") parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--tpath", "%s" % (path), - "--aname", "diva", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--gamma_y", "7e5", - "--gamma_d", "7e5", - "--nname_dom", "conv_bn_pool_2" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--tpath", + "%s" % (path), + "--model", + "diva", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + "--gamma_y", + "7e5", + "--gamma_d", + "7e5", + "--nname_dom", + "conv_bn_pool_2", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) @@ -71,25 +98,35 @@ def test_trainer_diva_folder(): gc.collect() - def test_trainer_diva_pathlist(): testdir = os.path.dirname(os.path.realpath(__file__)) rootdir = os.path.join(testdir, "..") rootdir = os.path.abspath(rootdir) path = os.path.join(rootdir, "examples/tasks/demo_task_path_list_small.py") parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "sketch", - "--tpath", "%s" % (path), - "--aname", "diva", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--gamma_y", "7e5", - "--gamma_d", "7e5", - "--nname_dom", "conv_bn_pool_2" - ]) + margs = parser.parse_args( + [ + "--te_d", + "sketch", + "--tpath", + "%s" % (path), + "--model", + "diva", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + "--gamma_y", + "7e5", + "--gamma_d", + "7e5", + "--nname_dom", + "conv_bn_pool_2", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) del exp torch.cuda.empty_cache() gc.collect() - diff --git a/tests/test_encoder.py b/tests/test_encoder.py index eca4e1354..790f84d0b 100644 --- a/tests/test_encoder.py +++ b/tests/test_encoder.py @@ -1,6 +1,9 @@ import torch -from domainlab.compos.vae.compos.encoder_xyd_parallel import XYDEncoderParallelConvBnReluPool + from domainlab.compos.vae.compos.encoder import LSEncoderConvBnReluPool +from domainlab.compos.vae.compos.encoder_xyd_parallel import ( + XYDEncoderParallelConvBnReluPool, +) def test_XYDEncoderConvBnReluPool(): @@ -13,10 +16,12 @@ def test_XYDEncoderConvBnReluPool(): def test_LSEncoderConvStride1BnReluPool(): """test""" from domainlab.utils.test_img import mk_img + img_size = 28 img = mk_img(img_size) - model = LSEncoderConvBnReluPool(z_dim=8, i_channel=3, i_h=img_size, i_w=img_size, - conv_stride=1) + model = LSEncoderConvBnReluPool( + z_dim=8, i_channel=3, i_h=img_size, i_w=img_size, conv_stride=1 + ) q_zd, zd_q = model(img) q_zd.mean q_zd.scale diff --git a/tests/test_encoder_domain_topic.py b/tests/test_encoder_domain_topic.py index c2ce49d05..fd1376ea7 100644 --- a/tests/test_encoder_domain_topic.py +++ b/tests/test_encoder_domain_topic.py @@ -1,18 +1,16 @@ import torch -from domainlab.compos.vae.compos.encoder_domain_topic import EncoderSandwichTopicImg2Zd + from domainlab.arg_parser import mk_parser_main +from domainlab.compos.vae.compos.encoder_domain_topic import EncoderSandwichTopicImg2Zd def test_TopicImg2Zd(): parser = mk_parser_main() - args = parser.parse_args([ - "--te_d", "9", "--dpath", - "zout", "--split", "0.8"]) - args.nname_encoder_sandwich_layer_img2h4zd = "conv_bn_pool_2" + args = parser.parse_args(["--te_d", "9", "--dpath", "zout", "--split", "0.8"]) + args.nname_encoder_sandwich_x2h4zd = "conv_bn_pool_2" model = EncoderSandwichTopicImg2Zd( - zd_dim=64, i_c=3, i_h=64, i_w=64, - num_topics=5, topic_h_dim=1024, img_h_dim=1024, - args=args) + zd_dim=64, isize=(3, 64, 64), num_topics=5, img_h_dim=1024, args=args + ) x = torch.rand(20, 3, 64, 64) topic = torch.rand(20, 5) _, _ = model(x, topic) diff --git a/tests/test_exp_protocol.py b/tests/test_exp_protocol.py new file mode 100644 index 000000000..2f9ca03ea --- /dev/null +++ b/tests/test_exp_protocol.py @@ -0,0 +1,149 @@ +""" +Tests run_experiment.py +""" +import os +import shutil +from typing import List + +import pytest +import torch +import yaml + +from domainlab.arg_parser import mk_parser_main +from domainlab.exp_protocol.aggregate_results import agg_main, agg_results +from domainlab.exp_protocol.run_experiment import apply_dict_to_args, run_experiment + + +def test_run_experiment(): + utils_run_experiment( + "examples/benchmark/demo_benchmark.yaml", list_test_domains=["caltech"] + ) + utils_run_experiment( + "examples/benchmark/demo_benchmark_mnist4test.yaml", ["0"], no_run=False + ) + + +def utils_run_experiment(yaml_name, list_test_domains, no_run=True): + """Checks the run_experiment function on a minimal basis""" + with open(yaml_name, "r", encoding="utf8") as stream: + config = yaml.safe_load(stream) + if torch.cuda.is_available(): + torch.cuda.init() + config["epos"] = 1 + config["startseed"] = 1 + config["endseed"] = 1 + config["test_domains"] = list_test_domains + param_file = "data/ztest_files/test_parameter_samples.csv" + param_index = 0 + out_file = "zoutput/benchmarks/demo_benchmark/rule_results/0.csv" + + # setting misc={'testing': True} will disable experiment being executed + run_experiment(config, param_file, param_index, out_file, misc={"testing": True}) + # setting test_domain equals zero will also not execute the experiment + if no_run: + config["test_domains"] = [] + run_experiment(config, param_file, param_index, out_file) + + +def test_apply_dict_to_args(): + """Testing apply_dict_to_args""" + parser = mk_parser_main() + args = parser.parse_args(args=[]) + data = {"a": 1, "b": [1, 2], "model": "diva"} + apply_dict_to_args(args, data, extend=True) + assert args.a == 1 + assert args.model == "diva" + + +def create_agg_input_files() -> List[str]: + """Creates test input files.""" + test_dir = "zoutput/test/rule_results" + os.makedirs(test_dir, exist_ok=True) + f_0 = test_dir + "/0.csv" + f_1 = test_dir + "/1.csv" + + with open(f_0, "w") as stream: + stream.write( + "param_index, method, algo, epos, te_d, seed, params, acc," + " precision, recall, specificity, f1, aurocy\n" + "0, diva, diva, 2, caltech, 1, \"{'gamma_y': 682408," + " 'gamma_d': 275835}\", 0.88461536, 0.852381," + " 0.80833334, 0.80833334, 0.82705104, 0.98333335\n" + ) + + with open(f_1, "w") as stream: + stream.write( + "param_index, method, algo, epos, te_d, seed, params, acc," + " precision, recall, specificity, f1, aurocy\n" + "1, hduva, hduva, 2, caltech, 1, \"{'gamma_y': 70037," + " 'zy_dim': 48}\", 0.7307692, 0.557971," + " 0.5333333, 0.5333333, 0.5297158, 0.73333335" + ) + return [f_0, f_1] + + +def cleanup_agg_test_files(): + """Delete temporal test files.""" + shutil.rmtree("zoutput/test", ignore_errors=True) + + +@pytest.fixture +def agg_input_files() -> List[str]: + """Create test input files for the agg tests.""" + # let the test run + yield create_agg_input_files() + # cleanup test files. + cleanup_agg_test_files() + + +@pytest.fixture +def agg_output_file() -> str: + """Test output file for the agg tests.""" + # let the test run + yield "zoutput/test/results.csv" + # cleanup test files. + os.remove("zoutput/test/results.csv") + + +@pytest.fixture +def agg_expected_output() -> str: + """Expected result file content for the agg tests.""" + return ( + "param_index, method, algo, epos, te_d, seed, params, acc," + " precision, recall, specificity, f1, aurocy\n" + "0, diva, diva, 2, caltech, 1, \"{'gamma_y': 682408," + " 'gamma_d': 275835}\", 0.88461536, 0.852381," + " 0.80833334, 0.80833334, 0.82705104, 0.98333335\n" + "1, hduva, hduva, 2, caltech, 1, \"{'gamma_y': 70037," + " 'zy_dim': 48}\", 0.7307692, 0.557971," + " 0.5333333, 0.5333333, 0.5297158, 0.73333335" + ) + + +@pytest.fixture +def bm_config(): + """Test benchmark config.""" + create_agg_input_files() + # let the test run + yield "zoutput/test" + # cleanup test files. + cleanup_agg_test_files() + + +def compare_file_content(filename: str, expected: str) -> bool: + """Returns true if the given file contains the given string.""" + with open(filename, "r") as stream: + content = stream.readlines() + return "".join(content) == expected + + +def test_agg_results(agg_input_files, agg_output_file, agg_expected_output): + """Testing the csv aggregation from a list of files.""" + agg_results(agg_input_files, agg_output_file) + compare_file_content(agg_output_file, agg_expected_output) + + +def test_agg_main(bm_config, agg_output_file, agg_expected_output): + """Testing the csv aggregation from a full directory.""" + agg_main(bm_config, skip_plotting=True) + compare_file_content(agg_output_file, agg_expected_output) diff --git a/tests/test_fishr.py b/tests/test_fishr.py new file mode 100644 index 000000000..539c64a72 --- /dev/null +++ b/tests/test_fishr.py @@ -0,0 +1,12 @@ +""" +unit and end-end test for deep all, mldg +""" +from tests.utils_test import utils_test_algo + + +def test_deepall_mldg(): + """ + train DeepAll with MLDG + """ + args = "--te_d=caltech --task=mini_vlcs --debug --bs=2 --model=erm --trainer=fishr --nname=alexnet" + utils_test_algo(args) diff --git a/tests/test_git_tag.py b/tests/test_git_tag.py index 1aa42ab33..2bd96e146 100644 --- a/tests/test_git_tag.py +++ b/tests/test_git_tag.py @@ -1,13 +1,34 @@ -''' +""" Code coverage issues: https://app.codecov.io/gh/marrlab/DomainLab/blob/master/domainlab/utils/get_git_tag.py - lines 10-20 - lines 28, 30-32 -''' +""" from domainlab.utils.get_git_tag import get_git_tag + def test_git_tag(): """ test git_tag """ get_git_tag(print_diff=True) + + +def test_git_tag_error(): + """ + test git_tag error + """ + # add one line to the file + with open("data/ztest_files/dummy_file.py", "a") as f: + f.write("\n# I am a dummy command") + get_git_tag(print_diff=True) + # delete the last line on the file again + with open("data/ztest_files/dummy_file.py", "r") as f: + lines = f.readlines() + lines = lines[:-1] + with open("data/ztest_files/dummy_file.py", "w") as f: + for num, line in enumerate(lines): + if num == len(lines) - 1: + f.write(line[:-2]) + else: + f.write(line) diff --git a/tests/test_hduva.py b/tests/test_hduva.py index 2d870564a..1e904ab23 100644 --- a/tests/test_hduva.py +++ b/tests/test_hduva.py @@ -1,10 +1,27 @@ """ end to end test """ -import torch + import gc -from domainlab.compos.exp.exp_main import Exp + +import torch + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp +from tests.utils_test import utils_test_algo + + +def test_hduva_zx_nonzero(): + """ + the combination of dial and diva: use dial trainer to train diva model + """ + utils_test_algo( + "--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --zx_dim=8 \ + --model=hduva --nname=conv_bn_pool_2 \ + --nname_encoder_x2topic_h=conv_bn_pool_2 \ + --gamma_y=7e5 \ + --nname_encoder_sandwich_x2h4zd=conv_bn_pool_2" + ) def test_trainer_hduva(): @@ -12,18 +29,29 @@ def test_trainer_hduva(): end to end test """ parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "hduva", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--gamma_y", "7e5", - "--nname_topic_distrib_img2topic", "conv_bn_pool_2", - "--nname_encoder_sandwich_layer_img2h4zd", "alexnet" - ]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "hduva", + "--bs", + "2", + "--nname", + "alexnet", + "--gamma_y", + "7e5", + "--nname_encoder_x2topic_h", + "conv_bn_pool_2", + "--nname_encoder_sandwich_x2h4zd", + "conv_bn_pool_2", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) del exp torch.cuda.empty_cache() gc.collect() - diff --git a/tests/test_hduva_dirichlet_encoder.py b/tests/test_hduva_dirichlet_encoder.py new file mode 100644 index 000000000..749b0afa6 --- /dev/null +++ b/tests/test_hduva_dirichlet_encoder.py @@ -0,0 +1,18 @@ +""" +end to end test +""" +import torch + +from domainlab.compos.vae.compos.encoder_dirichlet import EncoderH2Dirichlet + + +def test_unit_encoder_dirichlet(): + encoder_dirichlet = EncoderH2Dirichlet(dim_topic=3, device=torch.device("cpu")) + feat_hidden_uniform01 = torch.rand(32, 3) # batchsize 32 + encoder_dirichlet(feat_hidden_uniform01) + feat_hidden_normal = torch.normal(0, 1, size=(32, 3)) + encoder_dirichlet(feat_hidden_normal) + feat_hidden_uniform_big = feat_hidden_uniform01 * 1e9 + encoder_dirichlet(feat_hidden_uniform_big) + feat_hidden_uniform_small = feat_hidden_uniform01 * 1e-9 + encoder_dirichlet(feat_hidden_uniform_small) diff --git a/tests/test_hyperparameter_sampling.py b/tests/test_hyperparameter_sampling.py index 7abbb51f1..5142cadd6 100644 --- a/tests/test_hyperparameter_sampling.py +++ b/tests/test_hyperparameter_sampling.py @@ -1,12 +1,22 @@ """ tests hyperparameter_sampling.py """ +import numpy as np import pandas as pd import pytest import yaml -from domainlab.utils.hyperparameter_sampling import \ - sample_hyperparameters, sample_parameters, get_hyperparameter +from domainlab.utils.hyperparameter_gridsearch import sample_gridsearch +from domainlab.utils.hyperparameter_sampling import ( + G_METHOD_NA, + G_MODEL_NA, + Hyperparameter, + SampledHyperparameter, + get_hyperparameter, + sample_hyperparameters, + sample_parameters, +) +from tests.utils_test import assert_frame_not_equal def test_hyperparameter_sampling(): @@ -16,69 +26,246 @@ def test_hyperparameter_sampling(): samples = sample_hyperparameters(config) - a1samples = samples[samples['algo'] == 'Algo1'] - for par in a1samples['params']: - assert par['p1'] < par['p2'] - assert par['p3'] < par['p2'] - assert par['p2'] % 1 == pytest.approx(0) - assert par['p4'] == par['p3'] - assert par['p5'] == 2 * par['p3'] / par['p1'] - - a2samples = samples[samples['algo'] == 'Algo2'] - for par in a2samples['params']: - assert par['p1'] % 2 == pytest.approx(1) - assert par['p2'] % 1 == pytest.approx(0) - assert par['p3'] == 2 * par['p2'] - p_4 = par['p4'] + a1samples = samples[samples[G_MODEL_NA] == "Algo1"] + for par in a1samples["params"]: + assert par["p1_shared"] < par["p1"] + assert par["p1"] < par["p2"] + assert par["p3"] < par["p2"] + assert par["p2"] % 1 == pytest.approx(0) + assert par["p4"] == par["p3"] + assert par["p5"] == 2 * par["p3"] / par["p1"] + + a2samples = samples[samples[G_MODEL_NA] == "Algo2"] + for par in a2samples["params"]: + assert par["p1"] % 2 == pytest.approx(1) + assert par["p2"] % 1 == pytest.approx(0) + assert par["p3"] == 2 * par["p2"] + p_4 = par["p4"] + assert p_4 == 30 or p_4 == 31 or p_4 == 100 + assert np.issubdtype(type(p_4), np.integer) + + a3samples = samples[samples[G_MODEL_NA] == "Algo3"] + assert not a3samples.empty + + # test the case with less parameter samples than shared samples + config["num_param_samples"] = 3 + sample_hyperparameters(config) + + +def test_fallback_solution_of_sample_parameters(): + """ + trying to meet the constrainds with the pool of presampled shared + hyperparameters may not be possible, in this case the shared + hyperparameters are sampled accoring to their config. + This case is tested in this function + """ + # define a task specific hyperparameter + config = {"distribution": "uniform", "min": 0, "max": 1, "step": 0} + par = SampledHyperparameter("p1", config) + init_params = [par] + # set a constrained with a shared hyperparameter + constraints = ["p1 > p1_shared"] + # set config for shared hyperparameter + shared_config = { + "num_shared_param_samples": 2, + "p1_shared": {"distribution": "uniform", "min": 0, "max": 10, "step": 0}, + } + # set the shared samples to values which do never meet the + # constrained with the task specific hyperparameter + shared_samples = pd.DataFrame( + [["all", "all", {"p1_shared": 5}], ["all", "all", {"p1_shared": 6}]], + columns=[G_METHOD_NA, G_MODEL_NA, "params"], + ) + sample_parameters( + init_params, + constraints, + shared_config=shared_config, + shared_samples=shared_samples, + ) + + +def test_hyperparameter_gridsearch(): + """Test sampling from yaml, including constraints""" + with open( + "examples/yaml/demo_hyperparameter_gridsearch.yml", "r", encoding="utf-8" + ) as stream: + config = yaml.safe_load(stream) + + samples = sample_gridsearch(config) + + a1samples = samples[samples[G_MODEL_NA] == "Algo1"] + for par in a1samples["params"]: + assert par["p1"] < par["p2"] + assert par["p3"] < par["p2"] + assert par["p2"] % 1 == pytest.approx(0) + assert np.issubdtype(type(par["p2"]), np.integer) + assert par["p4"] == par["p3"] + assert par["p5"] == 2 * par["p3"] / par["p1"] + assert par["p1_shared"] == par["p1"] + assert np.issubdtype(type(par["p9"]), np.integer) + assert par["p10"] % 1 == 0.5 + + a2samples = samples[samples[G_MODEL_NA] == "Algo2"] + for par in a2samples["params"]: + assert par["p1"] % 2 == pytest.approx(1) + assert par["p2"] % 1 == pytest.approx(0) + assert par["p3"] == 2 * par["p2"] + p_4 = par["p4"] assert p_4 == 30 or p_4 == 31 or p_4 == 100 + assert np.issubdtype(type(par["p4"]), np.integer) + assert "p2_shared" not in par.keys() - a3samples = samples[samples['algo'] == 'Algo3'] + a3samples = samples[samples[G_MODEL_NA] == "Algo3"] assert not a3samples.empty + assert "p1_shared" not in a3samples.keys() + assert "p2_shared" not in a3samples.keys() + + +def test_gridhyperparameter_errors(): + """Test for the errors which may occour in the sampling of the grid""" + with pytest.raises(RuntimeError, match="distance between max and min to small"): + sample_gridsearch( + { + "output_dir": "zoutput/benchmarks/test", + "Task1": { + "model": "Algo1", + "hyperparameters": { + "p1": { + "min": 0, + "max": 1, + "step": 5, + "distribution": "uniform", + "num": 2, + } + }, + }, + } + ) + + with pytest.raises(RuntimeError, match='distribution "random" not implemented'): + sample_gridsearch( + { + "output_dir": "zoutput/benchmarks/test", + "Task1": { + "model": "Algo1", + "hyperparameters": { + "p1": { + "min": 0, + "max": 1, + "step": 0, + "distribution": "random", + "num": 2, + } + }, + }, + } + ) + + with pytest.raises(RuntimeError, match="No valid value found"): + sample_gridsearch( + { + "output_dir": "zoutput/benchmarks/test", + "Task1": { + "model": "Algo1", + "hyperparameters": { + "p1": { + "min": 2, + "max": 3.5, + "step": 1, + "distribution": "uniform", + "num": 2, + }, + "p2": { + "min": 0, + "max": 1.5, + "step": 1, + "distribution": "uniform", + "num": 2, + }, + "constraints": ["p1 < p2"], + }, + }, + } + ) + + with pytest.raises( + RuntimeError, + match="the number of parameters in the grid " + "direction of p1 needs to be specified", + ): + sample_gridsearch( + { + "output_dir": "zoutput/benchmarks/test", + "Task1": { + "model": "Algo1", + "hyperparameters": { + "p1": {"min": 0, "max": 1, "step": 0, "distribution": "uniform"} + }, + }, + } + ) def test_hyperparameter_errors(): """Test for errors on unknown distribution or missing keys""" with pytest.raises(RuntimeError, match="Datatype unknown"): - par = get_hyperparameter('name', {'reference': 'a'}) + par = get_hyperparameter("name", {"reference": "a"}) par.datatype() - with pytest.raises(RuntimeError, match='Unsupported distribution'): - get_hyperparameter('name', {'distribution': 'unknown'}) + with pytest.raises(RuntimeError, match="Unsupported distribution"): + get_hyperparameter("name", {"distribution": "unknown"}) - with pytest.raises(RuntimeError, match='Missing required key'): - get_hyperparameter('name', {'distribution': 'uniform'}) + with pytest.raises(RuntimeError, match="Missing required key"): + get_hyperparameter("name", {"distribution": "uniform"}) - par = get_hyperparameter('name', {'distribution': 'uniform', 'min': 0, 'max': 1}) - par.distribution = 'unknown' - with pytest.raises(RuntimeError, match='Unsupported distribution'): + par = get_hyperparameter("name", {"distribution": "uniform", "min": 0, "max": 1}) + par.distribution = "unknown" + with pytest.raises(RuntimeError, match="Unsupported distribution"): par.sample() par.get_val() def test_constraint_error(): """Check error on invalid syntax in constraints""" - par = get_hyperparameter('name', {'distribution': 'uniform', 'min': 0, 'max': 1}) + par = get_hyperparameter("name", {"distribution": "uniform", "min": 0, "max": 1}) constraints = ["hello world"] - with pytest.raises(SyntaxError, match='Invalid syntax in yaml config'): + with pytest.raises(SyntaxError, match="Invalid syntax in yaml config"): sample_parameters([par], constraints) def test_sample_parameters_abort(): """Test for error on infeasible constraints""" - p_1 = get_hyperparameter('p1', {'distribution': 'uniform', 'min': 0, 'max': 1}) - p_2 = get_hyperparameter('p2', {'distribution': 'uniform', 'min': 2, 'max': 3}) - constraints = ['p2 < p1'] # impossible due to the bounds - with pytest.raises(RuntimeError, match='constraints reasonable'): + p_1 = get_hyperparameter("p1", {"distribution": "uniform", "min": 0, "max": 1}) + p_2 = get_hyperparameter("p2", {"distribution": "uniform", "min": 2, "max": 3}) + constraints = ["p2 < p1"] # impossible due to the bounds + with pytest.raises(RuntimeError, match="constraints reasonable"): sample_parameters([p_1, p_2], constraints) def test_sampling_seed(): """Tests if the same hyperparameters are sampled if sampling_seed is set""" - with open("examples/yaml/demo_hyperparameter_sampling.yml", "r") as stream: + with open( + "examples/yaml/demo_hyperparameter_sampling.yml", "r", encoding="utf8" + ) as stream: config = yaml.safe_load(stream) - config['sampling_seed'] = 1 + config["sampling_seed"] = 1 - samples1 = sample_hyperparameters(config) - samples2 = sample_hyperparameters(config) + samples1 = sample_hyperparameters(config, sampling_seed=config["sampling_seed"]) + samples2 = sample_hyperparameters(config, sampling_seed=config["sampling_seed"]) pd.testing.assert_frame_equal(samples1, samples2) + + +def test_sampling_seed_diff(): + """Tests if the same hyperparameters are sampled if sampling_seed is set""" + with open( + "examples/yaml/demo_hyperparameter_sampling.yml", "r", encoding="utf8" + ) as stream: + config = yaml.safe_load(stream) + + config["sampling_seed"] = 1 + samples1 = sample_hyperparameters(config, sampling_seed=config["sampling_seed"]) + + config["sampling_seed"] = 2 + samples2 = sample_hyperparameters(config, sampling_seed=config["sampling_seed"]) + assert_frame_not_equal(samples1, samples2) diff --git a/tests/test_jigen.py b/tests/test_jigen.py index 3e66b9dd3..e04dc17fc 100644 --- a/tests/test_jigen.py +++ b/tests/test_jigen.py @@ -9,21 +9,27 @@ def test_mnist_color_jigen(): """ color minst on jigen """ - utils_test_algo("--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=jigen \ - --nname=conv_bn_pool_2") + utils_test_algo( + "--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=jigen \ + --nname=conv_bn_pool_2" + ) def test_jigen30(): """ end to end test """ - utils_test_algo("--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=jigen \ - --nname=conv_bn_pool_2 --nperm=30") + utils_test_algo( + "--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=jigen \ + --nname=conv_bn_pool_2 --nperm=30" + ) def test_trainer_jigen100(): """ end to end test """ - utils_test_algo("--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --aname=jigen \ - --nname=conv_bn_pool_2 --nperm=100") + utils_test_algo( + "--te_d 0 1 2 --tr_d 3 7 --task=mnistcolor10 --model=jigen \ + --nname=conv_bn_pool_2 --nperm=100" + ) diff --git a/tests/test_matchdg.py b/tests/test_matchdg.py index a6a89ff35..9f95653db 100644 --- a/tests/test_matchdg.py +++ b/tests/test_matchdg.py @@ -1,21 +1,36 @@ import gc + import torch -from domainlab.compos.exp.exp_main import Exp + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp -def test_trainer_diva(): +def test_trainer_matchdg(): parser = mk_parser_main() - margs = parser.parse_args(["--te_d", "caltech", - "--task", "mini_vlcs", - "--aname", "matchdg", "--bs", "2", - "--nname", "conv_bn_pool_2", - "--epochs_ctr", "1", - "--epochs_erm", "1"]) + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--trainer", + "matchdg", + "--bs", + "2", + "--model", + "erm", + "--nname", + "conv_bn_pool_2", + "--epochs_ctr", + "1", + "--epos", + "3", + ] + ) exp = Exp(margs) exp.trainer.before_tr() exp.trainer.tr_epoch(0) del exp torch.cuda.empty_cache() gc.collect() - diff --git a/tests/test_matchduva.py b/tests/test_matchduva.py new file mode 100644 index 000000000..6c88decce --- /dev/null +++ b/tests/test_matchduva.py @@ -0,0 +1,15 @@ +""" +unit and end-end test for hduva, matchdg +""" +from tests.utils_test import utils_test_algo + + +def test_hduva_matchdg(): + """ + train HDUVA with MATCH + """ + args = "--te_d=caltech --task=mini_vlcs --debug --bs=2 --model=hduva --trainer=matchdg\ + --epochs_ctr=3 --epos=6 --nname=alexnet --gamma_y=7e5 \ + --nname_encoder_x2topic_h=conv_bn_pool_2 \ + --nname_encoder_sandwich_x2h4zd=alexnet" + utils_test_algo(args) diff --git a/tests/test_mk_exp_dann.py b/tests/test_mk_exp_dann.py new file mode 100644 index 000000000..3544b04bf --- /dev/null +++ b/tests/test_mk_exp_dann.py @@ -0,0 +1,79 @@ +""" +make an experiment using "dann" model +""" +from torch import nn +from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights + +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.mk_exp import mk_exp +from domainlab.models.model_dann import mk_dann +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize + + +def test_mk_exp_dann(): + """ + test mk experiment API with "dann" model and "mldg", "dial" trainers + """ + mk_exp_dann(trainer="basic") + mk_exp_dann(trainer="mldg") + mk_exp_dann(trainer="dial") + + +def mk_exp_dann(trainer="mldg"): + """ + execute experiment with "dann" model and arbitrary trainer + """ + + # specify domain generalization task + task = mk_task_dset(dim_y=10, isize=ImSize(3, 28, 28), taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + task.get_list_domains_tr_te(None, "domain1") + # specify task-specific parameters + num_output_net_classifier = task.dim_y + num_output_net_discriminator = len(task.list_domain_tr) + list_str_y = [f"class{i}" for i in range(num_output_net_classifier)] + alpha = 1e-3 + + # specify feature extractor as ResNet + net_encoder = torchvisionmodels.resnet.resnet50( + weights=ResNet50_Weights.IMAGENET1K_V2 + ) + num_output_net_encoder = net_encoder.fc.out_features + + # specify discriminator as linear network + net_discriminator = nn.Linear(num_output_net_encoder, num_output_net_discriminator) + + # specify net classifier as linear network + net_classifier = nn.Linear(num_output_net_encoder, num_output_net_classifier) + + # specify model to use + model = mk_dann( + list_str_y=list_str_y, + net_classifier= net_classifier + )( + task.list_domain_tr, + alpha, + net_encoder, + net_discriminator + ) + + # make trainer for model + + exp = mk_exp(task, model, trainer=trainer, test_domain="domain1", batchsize=32) + exp.execute(num_epochs=2) diff --git a/tests/test_mk_exp_deepall.py b/tests/test_mk_exp_deepall.py new file mode 100644 index 000000000..38c41f88a --- /dev/null +++ b/tests/test_mk_exp_deepall.py @@ -0,0 +1,57 @@ +""" +make an experiment using the "erm" model +""" +from torch import nn +from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights + +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.mk_exp import mk_exp +from domainlab.models.model_erm import mk_erm +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize + + +def test_mk_exp_erm(): + """ + test mk experiment API with "erm" model and "mldg", "dial" trainers + """ + + mk_exp_erm(trainer="mldg") + mk_exp_erm(trainer="dial") + + +def mk_exp_erm(trainer="mldg"): + """ + execute experiment with "erm" model and custom trainer + + """ + # specify domain generalization task + task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify backbone to use + backbone = torchvisionmodels.resnet.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + num_final_in = backbone.fc.in_features + backbone.fc = nn.Linear(num_final_in, task.dim_y) + + # specify model to use + model = mk_erm(list_str_y=task.list_str_y)(backbone) + + # make trainer for model + exp = mk_exp(task, model, trainer=trainer, test_domain="domain1", batchsize=32) + exp.execute(num_epochs=2) diff --git a/tests/test_mk_exp_diva.py b/tests/test_mk_exp_diva.py new file mode 100644 index 000000000..dd93452c9 --- /dev/null +++ b/tests/test_mk_exp_diva.py @@ -0,0 +1,87 @@ +""" +make an experiment using "diva" model +""" + +from domainlab.compos.pcr.request import RequestVAEBuilderNN +from domainlab.compos.vae.compos.encoder import LSEncoderConvBnReluPool +from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.mk_exp import mk_exp +from domainlab.models.model_diva import mk_diva +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize + + +def test_mk_exp_diva(): + """ + test mk experiment API for "diva" model and trainers "mldg", "dial" + """ + mk_exp_diva(trainer="mldg") + mk_exp_diva(trainer="dial") + + +def mk_exp_diva(trainer="mldg"): + """ + execute experiment with "diva" model and custom trainer + """ + + # specify domain generalization task + task = mk_task_dset(dim_y=10, isize=ImSize(3, 28, 28), taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + # specify parameters + list_str_y = [f"class{i}" for i in range(task.dim_y)] + list_d_tr = ["domain2", "domain3"] + zd_dim = 3 + zy_dim = 10 + zx_dim = 30 + gamma_d = 1e5 + gamma_y = 7e5 + beta_d = 1e3 + beta_x = 1e3 + beta_y = 1e3 + net_class_d = LSEncoderConvBnReluPool( + zd_dim, task.isize.c, task.isize.w, task.isize.h, conv_stride=1 + ) + net_x = LSEncoderConvBnReluPool( + zx_dim, task.isize.c, task.isize.w, task.isize.h, conv_stride=1 + ) + net_class_y = LSEncoderConvBnReluPool( + zy_dim, task.isize.c, task.isize.w, task.isize.h, conv_stride=1 + ) + + request = RequestVAEBuilderNN( + net_class_d, net_x, net_class_y, task.isize.c, task.isize.h, task.isize.w + ) + chain_node_builder = VAEChainNodeGetter(request)() + + # specify model to use + model = mk_diva(list_str_y=list_str_y)( + chain_node_builder, + zd_dim, + zy_dim, + zx_dim, + list_d_tr, + gamma_d, + gamma_y, + beta_d, + beta_x, + beta_y, + ) + + # make trainer for model + exp = mk_exp(task, model, trainer=trainer, test_domain="domain1", batchsize=32) + exp.execute(num_epochs=3) diff --git a/tests/test_mk_exp_jigen.py b/tests/test_mk_exp_jigen.py new file mode 100644 index 000000000..21c533489 --- /dev/null +++ b/tests/test_mk_exp_jigen.py @@ -0,0 +1,76 @@ +""" +make an experiment using "jigen" model +""" + +from torch import nn +from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights + +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.mk_exp import mk_exp +from domainlab.models.model_jigen import mk_jigen +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize + + +def test_mk_exp_jigen(): + """ + test mk experiment API with "jigen" model and "mldg", "dial" trainer + """ + + mk_exp_jigen(trainer="mldg") + mk_exp_jigen(trainer="dial") + + +def mk_exp_jigen(trainer="mldg"): + """ + test mk experiment API with "jigen" model and custom trainer + """ + + # specify domain generalization task: + task = mk_task_dset(dim_y=10, isize=ImSize(3, 28, 28), taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify parameters + num_output_net_classifier = task.dim_y + num_output_net_permutation = 32 # 31+1 + list_str_y = [f"class{i}" for i in range(num_output_net_classifier)] + coeff_reg = 1e-3 + + # specify net encoder + net_encoder = torchvisionmodels.resnet.resnet50( + weights=ResNet50_Weights.IMAGENET1K_V2 + ) + num_output_net_encoder = net_encoder.fc.out_features + + # specify permutation classifier as linear network + net_permutation = nn.Linear(num_output_net_encoder, num_output_net_permutation) + + # specify label classifier as linear network + net_classifier = nn.Linear(num_output_net_encoder, num_output_net_classifier) + + # specify model to use + model = mk_jigen( + list_str_y=list_str_y, + net_classifier=net_classifier)( + net_encoder, + net_permutation, + coeff_reg) + + # make trainer for model + exp = mk_exp(task, model, trainer=trainer, test_domain="domain1", batchsize=32) + exp.execute(num_epochs=2) diff --git a/tests/test_mldg.py b/tests/test_mldg.py new file mode 100644 index 000000000..d2fb552e2 --- /dev/null +++ b/tests/test_mldg.py @@ -0,0 +1,12 @@ +""" +unit and end-end test for deep all, mldg +""" +from tests.utils_test import utils_test_algo + + +def test_erm_mldg(): + """ + train DeepAll with MLDG + """ + args = "--te_d=caltech --task=mini_vlcs --debug --bs=8 --model=erm --trainer=mldg --nname=alexnet" + utils_test_algo(args) diff --git a/tests/test_model_diva.py b/tests/test_model_diva.py index 598f45d8d..15ad609c7 100644 --- a/tests/test_model_diva.py +++ b/tests/test_model_diva.py @@ -1,10 +1,9 @@ - -from domainlab.models.model_diva import mk_diva -from domainlab.utils.utils_classif import mk_dummy_label_list_str -from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter -from domainlab.compos.pcr.request import RequestVAEBuilderCHW from domainlab.arg_parser import mk_parser_main +from domainlab.compos.pcr.request import RequestVAEBuilderCHW +from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter +from domainlab.models.model_diva import mk_diva from domainlab.utils.test_img import mk_rand_xyd +from domainlab.utils.utils_classif import mk_dummy_label_list_str def test_model_diva(): @@ -19,9 +18,18 @@ def test_model_diva(): request = RequestVAEBuilderCHW(3, 28, 28, args=margs) node = VAEChainNodeGetter(request)() - model = mk_diva()(node, zd_dim=8, zy_dim=8, zx_dim=8, list_d_tr=list_str_d, - list_str_y=list_str_y, gamma_d=1.0, gamma_y=1.0, - beta_d=1.0, beta_y=1.0, beta_x=1.0) + model = mk_diva(list_str_y=list_str_y)( + node, + zd_dim=8, + zy_dim=8, + zx_dim=8, + list_d_tr=list_str_d, + gamma_d=1.0, + gamma_y=1.0, + beta_d=1.0, + beta_y=1.0, + beta_x=1.0, + ) imgs, y_s, d_s = mk_rand_xyd(28, y_dim, 2, 2) _, _, _, _, _ = model.infer_y_vpicn(imgs) model(imgs, y_s, d_s) diff --git a/tests/test_msel_oracle.py b/tests/test_msel_oracle.py new file mode 100644 index 000000000..3dfdd6fbe --- /dev/null +++ b/tests/test_msel_oracle.py @@ -0,0 +1,265 @@ +""" +executing mk_exp multiple times will cause deep copy to be called multiple times, pytest will show process got killed. +""" +from torch import nn +from torchvision import models as torchvisionmodels +from torchvision.models import ResNet50_Weights + +from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_val import MSelValPerf +from domainlab.algos.observers.b_obvisitor import ObVisitor +from domainlab.arg_parser import mk_parser_main +from domainlab.dsets.dset_mnist_color_solo_default import DsetMNISTColorSoloDefault +from domainlab.exp.exp_main import Exp +from domainlab.models.model_erm import mk_erm +from domainlab.tasks.task_dset import mk_task_dset +from domainlab.tasks.utils_task import ImSize +from domainlab.utils.utils_cuda import get_device + + +def mk_exp( + task, + model, + trainer: str, + test_domain: str, + batchsize: int, + alone=True, + force_best_val=False, + msel_loss_tr=False, +): + """ + Creates a custom experiment. The user can specify the input parameters. + + Input Parameters: + - task: create a task to a custom dataset by importing "mk_task_dset" + function from + "domainlab.tasks.task_dset". For more explanation on the input params + refer to the + documentation found in "domainlab.tasks.task_dset.py". + - model: create a model [NameOfModel] by importing "mk_[NameOfModel]" + function from + "domainlab.models.model_[NameOfModel]". For a concrete example and + explanation of the input + params refer to the documentation found in + "domainlab.models.model_[NameOfModel].py" + - trainer: string, + - test_domain: string, + - batch size: int + + Returns: experiment + """ + + str_arg = f"--model=apimodel --trainer={trainer} \ + --te_d={test_domain} --bs={batchsize}" + if msel_loss_tr: + str_arg = f"--model=apimodel --trainer={trainer} \ + --te_d={test_domain} --bs={batchsize} --msel=loss_tr" + + parser = mk_parser_main() + conf = parser.parse_args(str_arg.split()) + device = get_device(conf) + if alone: + model_sel = MSelOracleVisitor() + else: + model_sel = MSelOracleVisitor(MSelValPerf(max_es=0)) + if force_best_val: + model_sel.msel._best_val_acc = 1.0 + observer = ObVisitor(model_sel) + exp = Exp(conf, task, model=model, observer=observer) + model_sel.update(clear_counter=True) + return exp + + +def test_msel_oracle(): + """ + return trainer, model, observer + """ + task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify backbone to use + backbone = torchvisionmodels.resnet.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + num_final_in = backbone.fc.in_features + backbone.fc = nn.Linear(num_final_in, task.dim_y) + + # specify model to use + model = mk_erm(list_str_y=task.list_str_y)(backbone) + + # make trainer for model + exp = mk_exp(task, model, trainer="mldg", test_domain="domain1", batchsize=32) + exp.execute(num_epochs=2) + + del exp + + +def test_msel_oracle1(): + """ + return trainer, model, observer + """ + task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify backbone to use + backbone = torchvisionmodels.resnet.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + num_final_in = backbone.fc.in_features + backbone.fc = nn.Linear(num_final_in, task.dim_y) + + # specify model to use + model = mk_erm(list_str_y=task.list_str_y)(backbone) + + # make trainer for model + + exp = mk_exp( + task, model, trainer="mldg", test_domain="domain1", batchsize=32, alone=False + ) + + exp.execute(num_epochs=2) + exp.trainer.observer.model_sel.msel.update(clear_counter=True) + del exp + + +def test_msel_oracle2(): + """ + return trainer, model, observer + """ + task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify backbone to use + backbone = torchvisionmodels.resnet.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + num_final_in = backbone.fc.in_features + backbone.fc = nn.Linear(num_final_in, task.dim_y) + + # specify model to use + model = mk_erm(list_str_y=task.list_str_y)(backbone) + + # make trainer for model + exp = mk_exp(task, model, trainer="mldg", test_domain="domain1", batchsize=32) + exp.execute(num_epochs=2) + + +def test_msel_oracle3(): + """ + return trainer, model, observer + """ + task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify backbone to use + backbone = torchvisionmodels.resnet.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + num_final_in = backbone.fc.in_features + backbone.fc = nn.Linear(num_final_in, task.dim_y) + + # specify model to use + model = mk_erm(list_str_y=task.list_str_y)(backbone) + + exp = mk_exp( + task, + model, + trainer="mldg", + test_domain="domain1", + batchsize=32, + alone=False, + force_best_val=True, + ) + exp.execute(num_epochs=2) + del exp + + +def test_msel_oracle4(): + """ + return trainer, model, observer + """ + task = mk_task_dset(isize=ImSize(3, 28, 28), dim_y=10, taskna="custom_task") + task.add_domain( + name="domain1", + dset_tr=DsetMNISTColorSoloDefault(0), + dset_val=DsetMNISTColorSoloDefault(1), + ) + task.add_domain( + name="domain2", + dset_tr=DsetMNISTColorSoloDefault(2), + dset_val=DsetMNISTColorSoloDefault(3), + ) + task.add_domain( + name="domain3", + dset_tr=DsetMNISTColorSoloDefault(4), + dset_val=DsetMNISTColorSoloDefault(5), + ) + + # specify backbone to use + backbone = torchvisionmodels.resnet.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + num_final_in = backbone.fc.in_features + backbone.fc = nn.Linear(num_final_in, task.dim_y) + + # specify model to use + model = mk_erm(list_str_y=task.list_str_y)(backbone) + exp = mk_exp( + task, + model, + trainer="mldg", + test_domain="domain1", + batchsize=32, + alone=False, + msel_loss_tr=True, + ) + exp.execute(num_epochs=2) + exp.trainer.observer.model_sel.msel.best_loss = 0 + exp.trainer.observer.model_sel.msel.update(clear_counter=True) + del exp diff --git a/tests/test_msel_tr_loss.py b/tests/test_msel_tr_loss.py new file mode 100644 index 000000000..f11428497 --- /dev/null +++ b/tests/test_msel_tr_loss.py @@ -0,0 +1,15 @@ +""" +unit and end-end test for deep all, dann +""" +from tests.utils_test import utils_test_algo + + +def test_erm(): + """ + unit deep all + """ + utils_test_algo( + "--te_d 0 --tr_d 3 7 --task=mnistcolor10 \ + --model=erm --nname=conv_bn_pool_2 --bs=2 \ + --msel=loss_tr --epos=2" + ) diff --git a/tests/test_observer.py b/tests/test_observer.py new file mode 100644 index 000000000..1a3f27bfb --- /dev/null +++ b/tests/test_observer.py @@ -0,0 +1,67 @@ +""" +unit and end-end test for deep all, dann +""" +import gc + +import torch + +from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp + + +def test_erm(): + """ + unit deep all + """ + parser = mk_parser_main() + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "erm", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + ] + ) + exp = Exp(margs) + exp.trainer.before_tr() + exp.trainer.tr_epoch(0) + exp.trainer.observer.update(True) + del exp + torch.cuda.empty_cache() + gc.collect() + + +def test_erm_trloss(): + """ + unit deep all + """ + parser = mk_parser_main() + margs = parser.parse_args( + [ + "--te_d", + "caltech", + "--task", + "mini_vlcs", + "--model", + "erm", + "--bs", + "2", + "--nname", + "conv_bn_pool_2", + "--msel", + "loss_tr", + ] + ) + exp = Exp(margs) + exp.trainer.before_tr() + exp.trainer.tr_epoch(0) + exp.trainer.observer.update(True) + del exp + torch.cuda.empty_cache() + gc.collect() diff --git a/tests/test_run_experiment.py b/tests/test_run_experiment.py index f5a158927..b22593a91 100644 --- a/tests/test_run_experiment.py +++ b/tests/test_run_experiment.py @@ -1,37 +1,69 @@ """ Tests run_experiment.py """ +import pytest import torch import yaml -from domainlab.arg_parser import mk_parser_main -from domainlab.exp_protocol.run_experiment import run_experiment, apply_dict_to_args +from domainlab.exp_protocol.run_experiment import run_experiment def test_run_experiment(): """Checks the run_experiment function on a minimal basis""" - with open("examples/yaml/demo_benchmark.yaml", "r", encoding="utf8") as stream: + with open("examples/benchmark/demo_benchmark.yaml", "r", encoding="utf8") as stream: config = yaml.safe_load(stream) if torch.cuda.is_available(): torch.cuda.init() - config['epos'] = 1 - config['startseed'] = 1 - config['endseed'] = 1 - config['test_domains'] = ['caltech'] + config["epos"] = 1 + config["startseed"] = 1 + config["endseed"] = 1 + config["test_domains"] = ["caltech"] param_file = "data/ztest_files/test_parameter_samples.csv" param_index = 0 out_file = "zoutput/benchmarks/demo_benchmark/rule_results/0.csv" - run_experiment(config, param_file, param_index, out_file, misc={'testing': True}) - config['test_domains'] = [] + run_experiment(config, param_file, param_index, out_file, misc={"testing": True}) + config["test_domains"] = [] run_experiment(config, param_file, param_index, out_file) + config["domainlab_args"]["batchsize"] = 16 + with pytest.raises(ValueError): + run_experiment(config, param_file, param_index, out_file) -def test_apply_dict_to_args(): - """Testing apply_dict_to_args""" - parser = mk_parser_main() - args = parser.parse_args(args=[]) - data = {'a': 1, 'b': [1, 2], 'aname': 'diva'} - apply_dict_to_args(args, data, extend=True) - assert args.a == 1 - assert args.aname == 'diva' + +def test_run_experiment_parameter_doubling_error(): + """checks if a hyperparameter is specified multiple times, + in the sympling section, in the common_args section and in the task section""" + with open("examples/benchmark/demo_benchmark.yaml", "r", encoding="utf8") as stream: + config = yaml.safe_load(stream) + config["epos"] = 1 + config["startseed"] = 1 + config["endseed"] = 1 + config["test_domains"] = ["caltech"] + config["diva"]["gamma_y"] = 1e4 + param_file = "data/ztest_files/test_parameter_samples.csv" + param_index = 0 + out_file = "zoutput/benchmarks/demo_benchmark/rule_results/0.csv" + + with pytest.raises( + RuntimeError, + match="has already been fixed " "to a value in the algorithm section.", + ): + run_experiment(config, param_file, param_index, out_file) + + with open("examples/benchmark/demo_benchmark.yaml", "r", encoding="utf8") as stream: + config = yaml.safe_load(stream) + config["epos"] = 1 + config["startseed"] = 1 + config["endseed"] = 1 + config["test_domains"] = ["caltech"] + config["domainlab_args"]["gamma_y"] = 1e4 + param_file = "data/ztest_files/test_parameter_samples.csv" + param_index = 0 + out_file = "zoutput/benchmarks/demo_benchmark/rule_results/0.csv" + + with pytest.raises( + RuntimeError, + match="has already been fixed " "to a value in the domainlab_args section.", + ): + run_experiment(config, param_file, param_index, out_file) diff --git a/tests/test_sav_img_title.py b/tests/test_sav_img_title.py index 4f5870659..b6743d476 100644 --- a/tests/test_sav_img_title.py +++ b/tests/test_sav_img_title.py @@ -1,23 +1,27 @@ -''' +""" Code coverage issues: https://app.codecov.io/gh/marrlab/DomainLab/blob/master/domainlab/utils/utils_img_sav.py - lines 22-23 - lines 31-35 -''' +""" import torch + from domainlab.utils.utils_img_sav import mk_fun_sav_img, sav_add_title + def test_save_img(): """ test sav_img function """ imgs = torch.randn(1, 3, 28, 28) tt_sav_img = mk_fun_sav_img() - tt_sav_img(imgs, name='rand_img.png', title='random_img') + tt_sav_img(imgs, name="rand_img.png", title="random_img") + + def test_add_title(): """ test sav_add_title """ img = torch.randn(3, 28, 28) - sav_add_title(img, path='.', title='random_img') + sav_add_title(img, path=".", title="random_img") diff --git a/tests/test_task.py b/tests/test_task.py new file mode 100644 index 000000000..9b04c5428 --- /dev/null +++ b/tests/test_task.py @@ -0,0 +1,6 @@ +from domainlab.tasks import get_task + + +def test_task_gettter(): + task = get_task("mini_vlcs") + print(task) diff --git a/tests/test_task_dset.py b/tests/test_task_dset.py new file mode 100644 index 000000000..b257b3389 --- /dev/null +++ b/tests/test_task_dset.py @@ -0,0 +1,13 @@ +""" +end to end test if the task constructed via dictionary of dsets works +""" +from tests.utils_test import utils_test_algo + + +def test_task_dset(): + """ + end to end test if the task constructed via dictionary of dsets works + """ + args = "--te_d=0 --tpath=examples/tasks/task_dset_custom.py --debug --bs=2 \ + --nname=conv_bn_pool_2 --model=erm" + utils_test_algo(args) diff --git a/tests/test_task_folder.py b/tests/test_task_folder.py index a811b9ee9..3b78b5f2c 100644 --- a/tests/test_task_folder.py +++ b/tests/test_task_folder.py @@ -1,53 +1,52 @@ import os + import pytest from torchvision import transforms from domainlab.arg_parser import mk_parser_main -from domainlab.tasks.task_folder_mk import mk_task_folder from domainlab.tasks.task_folder import NodeTaskFolder +from domainlab.tasks.task_folder_mk import mk_task_folder from domainlab.tasks.utils_task import ImSize + path_this_file = os.path.dirname(os.path.realpath(__file__)) def test_fun(): - node = mk_task_folder(extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", - "stuhl": "chair"}, - "sun": {"vehicle": "car", - "sofa": "chair"}, - "labelme": {"drive": "car", - "sit": "chair"} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "sun": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "labelme": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": - "data/vlcs_mini/caltech/", - "sun": - "data/vlcs_mini/sun/", - "labelme": - "data/vlcs_mini/labelme/"}, - taskna="mini_vlcs", - succ=None) + node = mk_task_folder( + extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, + list_str_y=["chair", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "stuhl": "chair"}, + "sun": {"vehicle": "car", "sofa": "chair"}, + "labelme": {"drive": "car", "sit": "chair"}, + }, + dict_domain_img_trans={ + "caltech": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "sun": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "labelme": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + }, + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": "data/vlcs_mini/caltech/", + "sun": "data/vlcs_mini/sun/", + "labelme": "data/vlcs_mini/labelme/", + }, + taskna="mini_vlcs", + succ=None, + ) parser = mk_parser_main() # batchsize bs=2 ensures it works on small dataset - args = parser.parse_args(["--te_d", "1", "--bs", "2", "--aname", "diva"]) + args = parser.parse_args(["--te_d", "1", "--bs", "2", "--model", "diva"]) node.init_business(args) node.get_list_domains() print(node.list_str_y) @@ -68,197 +67,211 @@ def test_fun(): # folder=folder_na, # batches=10) + def test_mk_task_folder(): - _ = mk_task_folder(extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", "stuhl": "chair"}, - "sun": {"viehcle": "car", "sofa": "chair"}, - "labelme": {"drive": "car", "sit": "chair"} - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), + _ = mk_task_folder( + extensions={"caltech": "jpg", "sun": "jpg", "labelme": "jpg"}, + list_str_y=["chair", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "stuhl": "chair"}, + "sun": {"viehcle": "car", "sofa": "chair"}, + "labelme": {"drive": "car", "sit": "chair"}, + }, + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + dict_domain_img_trans={ + "caltech": transforms.Compose( + [ + transforms.Resize((224, 224)), + ] + ), + "sun": transforms.Compose( + [ + transforms.Resize((224, 224)), + ] + ), + "labelme": transforms.Compose( + [ + transforms.Resize((224, 224)), + ] + ), + }, + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": "data/vlcs_mini/caltech/", + "sun": "data/vlcs_mini/sun/", + "labelme": "data/vlcs_mini/labelme/", + }, + taskna="mini_vlcs", + ) - dict_domain_img_trans={ - "caltech": transforms.Compose([transforms.Resize((224, 224)), ]), - "sun": transforms.Compose([transforms.Resize((224, 224)), ]), - "labelme": transforms.Compose([transforms.Resize((224, 224)), ]), - }, - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": "data/vlcs_mini/caltech/", - "sun": "data/vlcs_mini/sun/", - "labelme": "data/vlcs_mini/labelme/"}, - taskna="mini_vlcs") def test_none_extensions(): """Check if all different datatypes for the extensions arg work.""" - node = mk_task_folder(extensions={'caltech': None, 'labelme': None, 'sun': None}, - list_str_y=["chair", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", - "stuhl": "chair"}, - "sun": {"vehicle": "car", - "sofa": "chair"}, - "labelme": {"drive": "car", - "sit": "chair"} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "sun": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "labelme": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": - "data/vlcs_mini/caltech/", - "labelme": - "data/vlcs_mini/labelme/", - "sun": - "data/vlcs_mini/sun/"}, - taskna="mini_vlcs", - succ=None) + node = mk_task_folder( + extensions={"caltech": None, "labelme": None, "sun": None}, + list_str_y=["chair", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "stuhl": "chair"}, + "sun": {"vehicle": "car", "sofa": "chair"}, + "labelme": {"drive": "car", "sit": "chair"}, + }, + dict_domain_img_trans={ + "caltech": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "sun": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "labelme": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + }, + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": "data/vlcs_mini/caltech/", + "labelme": "data/vlcs_mini/labelme/", + "sun": "data/vlcs_mini/sun/", + }, + taskna="mini_vlcs", + succ=None, + ) parser = mk_parser_main() # batchsize bs=2 ensures it works on small dataset - args = parser.parse_args(["--te_d", "1", "--bs", "2", "--aname", "diva"]) + args = parser.parse_args(["--te_d", "1", "--bs", "2", "--model", "diva"]) node.init_business(args) - assert node.dict_domain_class_count['caltech']['chair'] == 6 - assert node.dict_domain_class_count['caltech']['car'] == 20 + assert node.dict_domain_class_count["caltech"]["chair"] == 6 + assert node.dict_domain_class_count["caltech"]["car"] == 20 # explicit given extension - node = mk_task_folder(extensions={'caltech': 'jpg', 'sun': 'jpg'}, - list_str_y=["bird", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", - "vogel": "bird"}, - 'sun': {'vehicle': 'car', - 'sofa': 'bird'} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "sun": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": - "data/mixed_codec/caltech/", - "sun": - "data/mixed_codec/sun/", - }, - taskna="mixed_codec", - succ=None) + node = mk_task_folder( + extensions={"caltech": "jpg", "sun": "jpg"}, + list_str_y=["bird", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "vogel": "bird"}, + "sun": {"vehicle": "car", "sofa": "bird"}, + }, + dict_domain_img_trans={ + "caltech": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "sun": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + }, + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": "data/mixed_codec/caltech/", + "sun": "data/mixed_codec/sun/", + }, + taskna="mixed_codec", + succ=None, + ) parser = mk_parser_main() # batchsize bs=2 ensures it works on small dataset - args = parser.parse_args(["--te_d", "1", "--bs", "2", "--aname", "diva"]) + args = parser.parse_args(["--te_d", "1", "--bs", "2", "--model", "diva"]) node.init_business(args) - assert node.dict_domain_class_count['caltech']['bird'] == 2,\ - "mixed_codec/caltech holds 2 jpg birds" - assert node.dict_domain_class_count['caltech']['car'] == 2,\ - "mixed_codec/caltech holds 2 jpg cars" + assert ( + node.dict_domain_class_count["caltech"]["bird"] == 2 + ), "mixed_codec/caltech holds 2 jpg birds" + assert ( + node.dict_domain_class_count["caltech"]["car"] == 2 + ), "mixed_codec/caltech holds 2 jpg cars" # No extensions given - node = mk_task_folder(extensions=None, - list_str_y=["bird", "car"], - dict_domain_folder_name2class={ - "caltech": {"auto": "car", - "vogel": "bird"}, - 'sun': {'vehicle': 'car', - 'sofa': 'bird'} - }, - dict_domain_img_trans={ - "caltech": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - "sun": transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - }, - img_trans_te=transforms.Compose( - [transforms.Resize((224, 224)), - transforms.ToTensor()]), - isize=ImSize(3, 224, 224), - dict_domain2imgroot={ - "caltech": - "data/mixed_codec/caltech/", - "sun": - "data/mixed_codec/sun/", - }, - taskna="mixed_codec", - succ=None) + node = mk_task_folder( + extensions=None, + list_str_y=["bird", "car"], + dict_domain_folder_name2class={ + "caltech": {"auto": "car", "vogel": "bird"}, + "sun": {"vehicle": "car", "sofa": "bird"}, + }, + dict_domain_img_trans={ + "caltech": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + "sun": transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + }, + img_trans_te=transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ), + isize=ImSize(3, 224, 224), + dict_domain2imgroot={ + "caltech": "data/mixed_codec/caltech/", + "sun": "data/mixed_codec/sun/", + }, + taskna="mixed_codec", + succ=None, + ) parser = mk_parser_main() # batchsize bs=2 ensures it works on small dataset - args = parser.parse_args(["--te_d", "1", "--bs", "2", "--aname", "diva"]) + args = parser.parse_args(["--te_d", "1", "--bs", "2", "--model", "diva"]) node.init_business(args) @pytest.fixture def pacs_node(): - """Task folder for PACS Mini 10 - """ + """Task folder for PACS Mini 10""" # FIXME: make me work with mk_task_folder node = NodeTaskFolder() node.set_list_domains(["cartoon", "photo"]) # node.extensions = {"cartoon": "jpg", "photo": "jpg"} - node.extensions = ('jpg',) + node.extensions = ("jpg",) node.list_str_y = ["dog", "elephant"] node.dict_domain2imgroot = { "cartoon": "data/pacs_mini_10/cartoon/", - "photo": "data/pacs_mini_10/photo/" + "photo": "data/pacs_mini_10/photo/", } return node @pytest.fixture def folder_args(): - """Test args; batchsize bs=2 ensures it works on small dataset - """ + """Test args; batchsize bs=2 ensures it works on small dataset""" parser = mk_parser_main() - args = parser.parse_args(["--te_d", "1", "--bs", "2", "--aname", "diva"]) + args = parser.parse_args(["--te_d", "1", "--bs", "2", "--model", "diva"]) return args + def test_nodetaskfolder(pacs_node, folder_args): - """Test NodeTaskFolder can be initiated without transforms - """ + """Test NodeTaskFolder can be initiated without transforms""" pacs_node.init_business(folder_args) def test_nodetaskfolder_transforms(pacs_node, folder_args): - """Test NodeTaskFolder can be initiated with transforms - """ + """Test NodeTaskFolder can be initiated with transforms""" pacs_node._dict_domain_img_trans = { - "cartoon": transforms.Compose([transforms.Resize((224, 224)), ]), - "photo": transforms.Compose([transforms.Resize((224, 224)), ]) + "cartoon": transforms.Compose( + [ + transforms.Resize((224, 224)), + ] + ), + "photo": transforms.Compose( + [ + transforms.Resize((224, 224)), + ] + ), } - pacs_node.img_trans_te = transforms.Compose([ - transforms.Resize((224, 224)), - transforms.ToTensor() - ]) + pacs_node.img_trans_te = transforms.Compose( + [transforms.Resize((224, 224)), transforms.ToTensor()] + ) pacs_node.init_business(folder_args) def test_nodetaskfolder_split_error(pacs_node, folder_args): - """Test NodeTaskFolder throws an error when split == True - """ + """Test NodeTaskFolder throws an error when split == True""" folder_args.split = True with pytest.raises(RuntimeError): pacs_node.init_business(folder_args) diff --git a/tests/test_train_diva.py b/tests/test_train_diva.py index 32c716ff8..9980e56be 100644 --- a/tests/test_train_diva.py +++ b/tests/test_train_diva.py @@ -1,22 +1,24 @@ import gc + import torch + +from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor +from domainlab.algos.msels.c_msel_tr_loss import MSelTrLoss from domainlab.algos.observers.b_obvisitor import ObVisitor +from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp +from domainlab.algos.trainers.train_hyper_scheduler import TrainerHyperScheduler +from domainlab.arg_parser import mk_parser_main +from domainlab.compos.pcr.request import RequestVAEBuilderCHW +from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter +from domainlab.exp.exp_main import Exp from domainlab.models.model_diva import mk_diva from domainlab.utils.utils_classif import mk_dummy_label_list_str -from domainlab.compos.vae.utils_request_chain_builder import VAEChainNodeGetter -from domainlab.compos.pcr.request import RequestVAEBuilderCHW -from domainlab.algos.trainers.train_visitor import TrainerVisitor -from domainlab.compos.exp.exp_main import Exp -from domainlab.arg_parser import mk_parser_main -from domainlab.algos.msels.c_msel_oracle import MSelOracleVisitor -from domainlab.algos.msels.c_msel import MSelTrLoss -from domainlab.algos.observers.c_obvisitor_cleanup import ObVisitorCleanUp from domainlab.utils.utils_cuda import get_device def test_trainer_diva(): parser = mk_parser_main() - argstr = "--te_d=rgb_31_119_180 --task=mnistcolor10 --aname=diva --bs=2 \ + argstr = "--te_d=rgb_31_119_180 --task=mnistcolor10 --model=diva --bs=2 \ --split 0.8 --nocu" margs = parser.parse_args(argstr.split()) @@ -28,14 +30,26 @@ def test_trainer_diva(): request = RequestVAEBuilderCHW(3, 28, 28, args=margs) node = VAEChainNodeGetter(request)() - model = mk_diva()(node, zd_dim=8, zy_dim=8, zx_dim=8, list_d_tr=list_str_d, - list_str_y=list_str_y, gamma_d=1.0, gamma_y=1.0, - beta_d=1.0, beta_y=1.0, beta_x=1.0) + model = mk_diva(list_str_y=list_str_y)( + node, + zd_dim=8, + zy_dim=8, + zx_dim=8, + list_d_tr=list_str_d, + gamma_d=1.0, + gamma_y=1.0, + beta_d=1.0, + beta_y=1.0, + beta_x=1.0, + ) model_sel = MSelOracleVisitor(MSelTrLoss(max_es=margs.es)) exp = Exp(margs) - device = get_device(flag_no_cu=False) - observer = ObVisitorCleanUp(ObVisitor(exp, model_sel, device)) - trainer = TrainerVisitor(model, task=exp.task, observer=observer, device=device, aconf=margs) + device = get_device(margs) + observer = ObVisitorCleanUp(ObVisitor(model_sel)) + trainer = TrainerHyperScheduler() + trainer.init_business( + model, task=exp.task, observer=observer, device=device, aconf=margs + ) trainer.before_tr() trainer.tr_epoch(0) del exp diff --git a/tests/test_unit_utils_task.py b/tests/test_unit_utils_task.py index ffb145b45..723674ece 100644 --- a/tests/test_unit_utils_task.py +++ b/tests/test_unit_utils_task.py @@ -1,5 +1,5 @@ -from domainlab.tasks.utils_task import LoaderDomainLabel from domainlab.dsets.dset_poly_domains_mnist_color_default import DsetMNISTColorMix +from domainlab.tasks.utils_task import LoaderDomainLabel def test_unit_utils_task(): @@ -7,4 +7,3 @@ def test_unit_utils_task(): loader = LoaderDomainLabel(32, 3)(dset, 0, "0") batch = next(iter(loader)) assert batch[0].shape == (32, 3, 28, 28) - diff --git a/tests/test_utils.py b/tests/test_utils.py index 6f6310718..529552858 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,8 +2,8 @@ Tests the ExpProtocolAggWriter """ from domainlab.arg_parser import mk_parser_main -from domainlab.compos.exp.exp_main import Exp -from domainlab.compos.exp.exp_utils import ExpProtocolAggWriter +from domainlab.exp.exp_main import Exp +from domainlab.exp.exp_utils import ExpProtocolAggWriter from domainlab.exp_protocol.run_experiment import apply_dict_to_args from domainlab.utils.get_git_tag import get_git_tag @@ -20,15 +20,15 @@ def test_exp_protocol_agg_writer(): parser = mk_parser_main() args = parser.parse_args(args=[]) misc = { - 'aname': 'diva', - 'nname': 'conv_bn_pool_2', - 'nname_dom': 'conv_bn_pool_2', - 'task': 'mnistcolor10', - 'te_d': 0, - 'result_file': "out_file", - 'params': "hyperparameters", - 'benchmark_task_name': "task", - 'param_index': 0 + "model": "diva", + "nname": "conv_bn_pool_2", + "nname_dom": "conv_bn_pool_2", + "task": "mnistcolor10", + "te_d": 0, + "result_file": "out_file", + "params": "hyperparameters", + "benchmark_task_name": "task", + "param_index": 0, } apply_dict_to_args(args, misc, extend=True) diff --git a/tests/this_is_not_a_network.py b/tests/this_is_not_a_network.py new file mode 100644 index 000000000..505da90f0 --- /dev/null +++ b/tests/this_is_not_a_network.py @@ -0,0 +1,14 @@ +""" +for testing one needs a network, which is actually not a network +""" + + +def build_feat_extract_net(dim_y, remove_last_layer): + """ + I am not a neuronal network + """ + # I had to add these two prints to satisfy the requirements of codacy + # to use all arguments given to a function + print(str(remove_last_layer)) + print(str(dim_y)) + return None diff --git a/tests/utils_test.py b/tests/utils_test.py index 178ed3bde..a8dd04177 100644 --- a/tests/utils_test.py +++ b/tests/utils_test.py @@ -3,9 +3,12 @@ helper function to execute as if command line arguments are passed """ import gc + +import pandas as pd import torch -from domainlab.compos.exp.exp_main import Exp + from domainlab.arg_parser import mk_parser_main +from domainlab.exp.exp_main import Exp def utils_test_algo(argsstr="--help"): @@ -19,3 +22,17 @@ def utils_test_algo(argsstr="--help"): del exp torch.cuda.empty_cache() gc.collect() + + +def assert_frame_not_equal(*args, **kwargs): + """ + use try except to assert frame not equal in pandas + """ + try: + pd.testing.assert_frame_equal(*args, **kwargs) + except AssertionError: + # frames are not equal + pass + else: + # frames are equal + raise AssertionError diff --git a/uml/libDG.uml b/uml/libDG.uml new file mode 100644 index 000000000..02c29d729 --- /dev/null +++ b/uml/libDG.uml @@ -0,0 +1,144 @@ +@startuml +' +' *-- composition +' <|-- extension +' o-- aggregation +' -- association (1 to n or 1 to 1 or n to 1) +' ..> +'Dependency is a weaker form of bond which indicates that one class depends on +'another because it uses it at some point in time. One class depends on +'another if the independent class is a parameter variable or local variable of +'a method of the dependent class. This is different from an association, where +'an attribute of the dependent class is an instance of the independent class. +'Sometimes the relationship between two classes is very weak. They are not +'implemented with member variables at all. Rather they might be implemented as +'member function arguments. +package tasks { + abstract class Task { + - transformations + - datasets (training domains) + - datasets (test domains) + } + Task <|-- TaskFolder + Task <|-- TaskPathList +} + +package algos { + abstract class AlgoBuilder { + + build_model() + + build_trainer() + + build_observer() + + model_specific_task_processing() + } + class ConcreteAlgoBuilder { + + build_model() + + build_trainer() + + build_observer() + + model_specific_task_processing() + } + package trainers { + class Trainer { + + update_regularization_weight() + + update_model_parameter() + + calculate_loss() + - model + - observer + - task + } + } + package observer { + class Observer { + + trainer.model.calculate_metric() + } + } + package model_selection { + class ModelSel { + - early_stop + } + } +} + +package datasets <>{ + class Dataset { + +__get__item__() + } +} + +package YMLConfiguration <>{ +} + +package models{ + abstract class Model { + + extract_feature() + + calculate_task_loss() + + calculate_regularization_loss() + + calculate_metric() + } + abstract class ModelBuilder { + +build_model_componet() + } + class ConcreteModel { + + calculate_regularization_loss() + + extract_feature() + } + class ConcreteModelBuilder {} + package networks { + } +} + + + package experiment { + class Experiment { + - task + - trainer + + execute() + } + class TaskHandler{} + class AlgoHandler{} + } + + +interface UserInput{ +- task +- hyperparameters ++ read_yml_for_configuration() ++ command_line_arguments() +} + +protocol benchmark{ + + run_experiment() + + plot_results() + + read_yml_for_configuration() +} + + + +UserInput -- YMLConfiguration +UserInput -- tasks +UserInput -- TaskHandler +ModelBuilder <|-- ConcreteModelBuilder +UserInput -- AlgoHandler +Experiment --* benchmark +Trainer *-- Observer +Trainer *-- ConcreteModel +Task o-- Dataset +Model <|-- ConcreteModel +AlgoBuilder <|-- ConcreteAlgoBuilder +Model *-- ModelBuilder +ConcreteModel *-- networks +AlgoHandler *-- ConcreteAlgoBuilder +Experiment *-- TaskHandler +Experiment *-- AlgoHandler +TaskHandler *-- tasks +ConcreteModelBuilder -- networks + +ConcreteAlgoBuilder *-- Trainer +ConcreteAlgoBuilder -- ConcreteModel +ConcreteAlgoBuilder -- Observer +ConcreteAlgoBuilder -- Trainer +Observer *-- ModelSel + +ModelSel -- Observer +ConcreteModelBuilder --* ConcreteModel +benchmark -- UserInput +@enduml diff --git a/zmain/main.py b/zmain/main.py index 9e84b6665..b106e4348 100644 --- a/zmain/main.py +++ b/zmain/main.py @@ -1,6 +1,6 @@ -from domainlab.compos.exp.exp_main import Exp -from domainlab.compos.exp.exp_cuda_seed import set_seed # reproducibility from domainlab.arg_parser import parse_cmd_args +from domainlab.exp.exp_cuda_seed import set_seed # reproducibility +from domainlab.exp.exp_main import Exp if __name__ == "__main__": args = parse_cmd_args() diff --git a/zmain/main_gen.py b/zmain/main_gen.py index 0032bdad9..ad5da86e8 100644 --- a/zmain/main_gen.py +++ b/zmain/main_gen.py @@ -2,19 +2,21 @@ command line generate images """ import os + import torch -from domainlab.compos.exp.exp_cuda_seed import set_seed -from domainlab.tasks.zoo_tasks import TaskChainNodeGetter + from domainlab.arg_parser import mk_parser_main -from domainlab.utils.utils_cuda import get_device +from domainlab.exp.exp_cuda_seed import set_seed +from domainlab.tasks.zoo_tasks import TaskChainNodeGetter from domainlab.utils.flows_gen_img_model import fun_gen +from domainlab.utils.utils_cuda import get_device def main_gen(args, task=None, model=None, device=None): """ command line generate images """ - device = get_device(args.nocu) + device = get_device(args) node = TaskChainNodeGetter(args)() node.init_business(args) model = torch.load(args.mpath, map_location="cpu") @@ -25,8 +27,9 @@ def main_gen(args, task=None, model=None, device=None): if __name__ == "__main__": parser = mk_parser_main() - parser.add_argument('--mpath', type=str, default=None, - help="path for persisted model") + parser.add_argument( + "--mpath", type=str, default=None, help="path for persisted model" + ) args = parser.parse_args() set_seed(args.seed) main_gen(args) diff --git a/zmain/main_task.py b/zmain/main_task.py index d378779fa..9f5e3c595 100644 --- a/zmain/main_task.py +++ b/zmain/main_task.py @@ -1,10 +1,9 @@ """ probe task by saving images to folder with class and domain label """ -from domainlab.compos.exp.exp_cuda_seed import set_seed -from domainlab.tasks.zoo_tasks import TaskChainNodeGetter from domainlab.arg_parser import mk_parser_main - +from domainlab.exp.exp_cuda_seed import set_seed +from domainlab.tasks.zoo_tasks import TaskChainNodeGetter if __name__ == "__main__": parser = mk_parser_main()