├── requirements.txt ├── test ├── requirements.txt └── data │ ├── scene.npy │ ├── scene.ppm │ ├── scene_640.jpg │ ├── scene_640.npy │ ├── README.md │ ├── scene.nblocks2.result │ ├── scene.ops_4_4_4.result │ ├── scene.nblocks4.result │ ├── scene.no_arg.result │ └── scene.ops_8_8_8.result ├── download-lear.sh ├── .gitignore ├── sample ├── download-8scene.sh ├── feature_extraction.py └── scene_classification.py ├── setup.py ├── LICENSE ├── wercker.yml ├── README.md ├── test.py └── gistmodule.c /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | -------------------------------------------------------------------------------- /test/requirements.txt: -------------------------------------------------------------------------------- 1 | memory-profiler==0.54.0 2 | nose==1.3.7 3 | parameterized==0.6.1 4 | -------------------------------------------------------------------------------- /test/data/scene.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whitphx/lear-gist-python/HEAD/test/data/scene.npy -------------------------------------------------------------------------------- /test/data/scene.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whitphx/lear-gist-python/HEAD/test/data/scene.ppm -------------------------------------------------------------------------------- /test/data/scene_640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whitphx/lear-gist-python/HEAD/test/data/scene_640.jpg -------------------------------------------------------------------------------- /test/data/scene_640.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whitphx/lear-gist-python/HEAD/test/data/scene_640.npy -------------------------------------------------------------------------------- /download-lear.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | wget http://lear.inrialpes.fr/src/lear_gist-1.2.tgz 4 | tar zxvf lear_gist-1.2.tgz 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | lear_gist-1.2.tgz 3 | lear_gist-1.2 4 | *.o 5 | sample/spatial_envelope_256x256_static_8outdoorcategories* 6 | sample/features 7 | .python-version 8 | -------------------------------------------------------------------------------- /sample/download-8scene.sh: -------------------------------------------------------------------------------- 1 | wget http://people.csail.mit.edu/torralba/code/spatialenvelope/spatial_envelope_256x256_static_8outdoorcategories.zip 2 | unzip spatial_envelope_256x256_static_8outdoorcategories.zip -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | from distutils.core import setup 3 | from distutils.extension import Extension 4 | 5 | gistmodule = Extension( 6 | 'gist', 7 | sources=['lear_gist-1.2/gist.c', 'lear_gist-1.2/standalone_image.c', 8 | 'gistmodule.c'], 9 | extra_compile_args=['-DUSE_GIST', '-DSTANDALONE_GIST', '-std=gnu99'], 10 | include_dirs=[numpy.get_include()], 11 | libraries=['fftw3f']) 12 | 13 | setup(name='gist', 14 | version='0.5', 15 | description='A wrapper package of lear_gist', 16 | ext_modules=[gistmodule]) 17 | -------------------------------------------------------------------------------- /test/data/README.md: -------------------------------------------------------------------------------- 1 | * The original image of `scene.ppm` is downloaded from https://images.pexels.com/photos/414171/pexels-photo-414171.jpeg 2 | * `scene.no_arg.result` is the output of `./compute_gist scene.ppm`. 3 | * `scene.nblocks2.result` and `scene.nblocks4.result` are the outputs of `./compute_gist -nblocks 2 scene.ppm` and `./compute_gist -nblocks 4 scene.ppm` respectively. 4 | * `scene.ops_4_4_4` and `scene.ops_8_8_8` are the outputs of `./compute_gist -orientationsPerScale 4,4,4 scene.ppm` and `./compute_gist -orientationsPerScale 8,8,8 scene.ppm` respectively. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yuichiro Tsuchiya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sample/feature_extraction.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import listdir, mkdir 3 | from os.path import exists, isdir, join 4 | import numpy as np 5 | from skimage import transform 6 | from PIL import Image 7 | import gist 8 | 9 | argv = sys.argv 10 | argc = len(argv) 11 | 12 | if (argc < 3): 13 | print "Not enough arguments." 14 | quit(1) 15 | 16 | 17 | input_dir = argv[1] 18 | output_dir = argv[2] 19 | 20 | if (not exists(output_dir)): 21 | mkdir(output_dir) 22 | 23 | imsize = (128, 128) 24 | 25 | features = {} 26 | 27 | filenames = listdir(input_dir) 28 | for filename in filenames: 29 | filepath = join(input_dir, filename) 30 | 31 | try: 32 | pilimg = Image.open(filepath) 33 | except: 34 | continue 35 | 36 | img = np.asarray(pilimg) 37 | img_resized = transform.resize(img, imsize, preserve_range=True).astype(np.uint8) 38 | desc = gist.extract(img_resized) 39 | 40 | class_name = filename.split('_')[0] 41 | 42 | if (class_name in features): 43 | features[class_name] = np.vstack((features[class_name], desc)) 44 | else: 45 | features[class_name] = np.atleast_2d(desc) 46 | 47 | for class_name, desc_mat in features.items(): 48 | np.save(join(output_dir, class_name+'.npy'), desc_mat) -------------------------------------------------------------------------------- /wercker.yml: -------------------------------------------------------------------------------- 1 | box: 2 | id: python:3.6.6-jessie 3 | 4 | build: 5 | steps: 6 | - pip-install 7 | - pip-install: 8 | name: Install testing libraries 9 | requirements_file: test/requirements.txt 10 | - script: 11 | name: Download and install FFTW 12 | code: | 13 | wget -O fftw-3.3.8.tar.gz http://www.fftw.org/fftw-3.3.8.tar.gz 14 | tar xf fftw-3.3.8.tar.gz 15 | cd fftw-3.3.8 16 | ./configure --enable-single --enable-shared 17 | make 18 | make install 19 | ldconfig 20 | - script: 21 | name: Download lear_gist 22 | code: ./download-lear.sh 23 | - script: 24 | name: Build lear-gist-python 25 | code: python setup.py build_ext --inplace 26 | - script: 27 | name: Run tests 28 | code: python test.py 29 | 30 | build-python2.7: 31 | box: python:2.7.15-jessie 32 | steps: 33 | - pip-install 34 | - pip-install: 35 | name: Install testing libraries 36 | requirements_file: test/requirements.txt 37 | - script: 38 | name: Download and install FFTW 39 | code: | 40 | wget -O fftw-3.3.8.tar.gz http://www.fftw.org/fftw-3.3.8.tar.gz 41 | tar xf fftw-3.3.8.tar.gz 42 | cd fftw-3.3.8 43 | ./configure --enable-single --enable-shared 44 | make 45 | make install 46 | ldconfig 47 | - script: 48 | name: Download lear_gist 49 | code: ./download-lear.sh 50 | - script: 51 | name: Build lear-gist-python 52 | code: python setup.py build_ext --inplace 53 | - script: 54 | name: Run tests 55 | code: python test.py 56 | -------------------------------------------------------------------------------- /test/data/scene.nblocks2.result: -------------------------------------------------------------------------------- 1 | 0.0158 0.0527 0.0199 0.0557 0.0151 0.0450 0.0162 0.0455 0.0165 0.0437 0.0158 0.0433 0.0177 0.0534 0.0184 0.0491 0.0201 0.0751 0.0265 0.0604 0.0190 0.0580 0.0371 0.0630 0.0156 0.0445 0.0424 0.0606 0.0152 0.0478 0.0262 0.0646 0.0267 0.0530 0.0252 0.0654 0.0249 0.0397 0.0191 0.0542 0.0263 0.0421 0.0215 0.0501 0.0254 0.0655 0.0226 0.0547 0.0312 0.1074 0.0345 0.0756 0.0298 0.0822 0.0497 0.0786 0.0251 0.0498 0.0618 0.0663 0.0255 0.0514 0.0393 0.0786 0.0444 0.0656 0.0535 0.0805 0.0505 0.0813 0.0381 0.0775 0.0699 0.1567 0.0784 0.1097 0.0540 0.0996 0.1079 0.1159 0.0158 0.0638 0.0197 0.0650 0.0151 0.0549 0.0163 0.0532 0.0165 0.0540 0.0162 0.0519 0.0177 0.0642 0.0190 0.0585 0.0204 0.0878 0.0272 0.0712 0.0192 0.0688 0.0376 0.0740 0.0158 0.0541 0.0426 0.0711 0.0155 0.0577 0.0261 0.0748 0.0251 0.0622 0.0256 0.0756 0.0230 0.0466 0.0182 0.0630 0.0238 0.0491 0.0205 0.0582 0.0236 0.0716 0.0222 0.0628 0.0304 0.1170 0.0350 0.0853 0.0283 0.0882 0.0479 0.0857 0.0245 0.0572 0.0587 0.0746 0.0242 0.0605 0.0375 0.0887 0.0385 0.0738 0.0495 0.0847 0.0427 0.0858 0.0362 0.0810 0.0623 0.1580 0.0723 0.1099 0.0484 0.1023 0.0982 0.1169 0.0168 0.0918 0.0209 0.1046 0.0164 0.0796 0.0176 0.0866 0.0183 0.0787 0.0178 0.0903 0.0191 0.0885 0.0207 0.1022 0.0222 0.1204 0.0299 0.1201 0.0205 0.0962 0.0396 0.1248 0.0177 0.0786 0.0437 0.1185 0.0169 0.0824 0.0273 0.1211 0.0257 0.0831 0.0261 0.1111 0.0242 0.0656 0.0191 0.0939 0.0260 0.0661 0.0222 0.0937 0.0241 0.0856 0.0230 0.0988 0.0312 0.1369 0.0377 0.1330 0.0283 0.1088 0.0490 0.1346 0.0263 0.0764 0.0569 0.1041 0.0252 0.0813 0.0379 0.1268 0.0357 0.0907 0.0468 0.1197 0.0393 0.0987 0.0372 0.1097 0.0571 0.1597 0.0704 0.1523 0.0449 0.1060 0.0893 0.1546 2 | -------------------------------------------------------------------------------- /sample/scene_classification.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import listdir, makedirs 3 | from os.path import join, exists, splitext 4 | import numpy as np 5 | from sklearn.utils import shuffle 6 | from sklearn.externals import joblib 7 | from sklearn import linear_model 8 | import pickle 9 | 10 | # Configure 11 | train_by_all = False 12 | n_trains = 200 13 | 14 | # Read command line arguments 15 | argv = sys.argv 16 | argc = len(argv) 17 | if argc < 2: 18 | print "Not enough arguments." 19 | quit(0) 20 | 21 | if argc >=3: 22 | save_model = True 23 | model_save_dir = argv[2] 24 | else: 25 | save_model = False 26 | 27 | # Prepare directory 28 | feature_dir = argv[1] 29 | if save_model and not exists(model_save_dir): 30 | makedirs(model_save_dir) 31 | 32 | # Iteration to load features 33 | filenames = listdir(feature_dir) 34 | class_id = 0 35 | class_names = [] 36 | for filename in filenames: 37 | filepath = join(feature_dir, filename) 38 | if not exists(filepath): 39 | continue 40 | 41 | # Get class label 42 | class_name, _ = splitext(filename) 43 | 44 | # Load and shuffle features 45 | features = shuffle(np.load(filepath)) 46 | 47 | # Construct train set 48 | if train_by_all: 49 | n_trains = features.shape[0] 50 | 51 | ## Features 52 | try: 53 | train_feat = np.vstack((train_feat, features[0:n_trains,:])) 54 | except: 55 | train_feat = np.atleast_2d(features[0:n_trains,:]) 56 | 57 | ## Labels 58 | train_label_vec = np.ones(n_trains) * class_id 59 | try: 60 | train_label = np.hstack((train_label, train_label_vec)) 61 | except: 62 | train_label = train_label_vec 63 | 64 | # Construct test set 65 | if train_by_all: 66 | n_tests = 100 67 | else: 68 | n_tests = features.shape[0] - n_trains 69 | ind_test = features.shape[0] - n_tests 70 | 71 | # Features 72 | try: 73 | test_feat = np.vstack((test_feat, features[ind_test:])) 74 | except: 75 | test_feat = np.atleast_2d(features[ind_test:]) 76 | 77 | # Labels 78 | test_label_vec = np.ones(n_tests) * class_id 79 | try: 80 | test_label = np.hstack((test_label, test_label_vec)) 81 | except: 82 | test_label = test_label_vec 83 | 84 | # Preserve class label and its id 85 | class_names.append(class_name) 86 | class_id += 1 87 | 88 | # Shuffle train data 89 | train_feat, train_label = shuffle(train_feat, train_label) 90 | 91 | print "Train Classifier..." 92 | clf = linear_model.SGDClassifier(average=50, n_iter=20) 93 | clf.fit(train_feat, train_label) 94 | 95 | print "Predict..." 96 | acc = np.sum(clf.predict(test_feat) == test_label) * 1.0 / np.size(test_label) 97 | print "Accuracy: ", acc 98 | 99 | if save_model: 100 | print "Save model" 101 | joblib.dump(clf, join(model_save_dir, 'scene.pkl')) 102 | 103 | with open(join(model_save_dir, 'class_names.txt'), 'wb') as f: 104 | pickle.dump(class_names, f) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lear-gist-python 2 | [![wercker status](https://app.wercker.com/status/5285318d112056b85e8f3643e8a4b9aa/s/master "wercker status")](https://app.wercker.com/project/byKey/5285318d112056b85e8f3643e8a4b9aa) 3 | 4 | 5 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/D1D2ERWFG) 6 | 7 | Buy Me A Coffee 8 | 9 | [![GitHub Sponsors](https://img.shields.io/github/sponsors/whitphx?label=Sponsor%20me%20on%20GitHub%20Sponsors&style=social)](https://github.com/sponsors/whitphx) 10 | 11 | Python library to extract [A. Torralba's GIST descriptor](http://people.csail.mit.edu/torralba/code/spatialenvelope/). 12 | 13 | This is just a wrapper for [Lear's GIST implementation](http://lear.inrialpes.fr/software) written in C. It supports both Python 2 and Python 3 and was tested under Python 2.7.15 and Python 3.6.6 on Linux. 14 | 15 | ## How to build and install 16 | 17 | ### Pre-requirements 18 | Following packages must be installed before building and installing `lear-gist-python`. 19 | 20 | ##### numpy 21 | ```shell 22 | $ pip install numpy 23 | ``` 24 | 25 | ##### FFTW 26 | [FFTW](http://www.fftw.org/) is required to build lear_gist. 27 | Please download the source, then build and install like following. (Install guide is [here](http://www.fftw.org/fftw3_doc/Installation-on-Unix.html). Please refer for defail.) 28 | Make sure `--enable-single` and `--enable-shared` options are set to `./configure`. 29 | ```shell 30 | $ ./configure --enable-single --enable-shared 31 | $ make 32 | $ make install 33 | ``` 34 | 35 | Because: 36 | - lear-gist requires *float version* FFTW to work with (`--enable-single`). 37 | - lear-gist-python requires FFTW to be compiled with `-fPIC` option (`--enable-shared`). 38 | 39 | ### Build and install 40 | Download lear_gist 41 | ```shell 42 | $ ./download-lear.sh 43 | ``` 44 | 45 | Build and install 46 | ```shell 47 | $ python setup.py build_ext 48 | $ python setup.py install 49 | ``` 50 | 51 | If `fftw3f` is installed in non-standard path (for example, `$HOME/local`), 52 | use `-I` and `-L` options: 53 | ```shell 54 | $ python setup.py build_ext -I $HOME/local/include -L $HOME/local/lib 55 | ``` 56 | 57 | ## Usage 58 | ```python 59 | import gist 60 | import numpy as np 61 | 62 | img = ... # numpy array containing an image 63 | descriptor = gist.extract(img) 64 | ``` 65 | 66 | ## Scene classification sample 67 | This sample uses [8 Scene Categories Dataset](http://people.csail.mit.edu/torralba/code/spatialenvelope/). 68 | 69 | `scikit-learn` and `scikit-image` are required. 70 | ```shell 71 | $ pip install scikit-learn scikit-image 72 | ``` 73 | 74 | ```shell 75 | cd sample 76 | sh download-8scene.sh 77 | # Extract GIST features from images in "spatial_envelope_256x256_static_8outdoorcategories" directory and save them into "features" directory 78 | python feature_extraction.py spatial_envelope_256x256_static_8outdoorcategories features 79 | # Train and test a multi-class linear classifier by features in "features" directory 80 | python scene_classification.py features 81 | ``` 82 | 83 | ## API 84 | ### `gist.extract(img, nblocks=4, orientations_per_scale=(8, 8, 4))` 85 | * `img`: A numpy array (an instance of `numpy.ndarray`) which contains an image and whose shape is `(height, width, 3)`. 86 | * `nblocks`: Use a grid of `nblocks * nblocks` cells. 87 | * `orientations_per_scale`: Use `len(orientations_per_scale)` scales and compute `orientations_per_scale[i]` orientations for i-th scale. 88 | -------------------------------------------------------------------------------- /test/data/scene.ops_4_4_4.result: -------------------------------------------------------------------------------- 1 | 0.0236 0.0239 0.0699 0.0485 0.0236 0.0139 0.0815 0.0681 0.0217 0.0286 0.0926 0.0659 0.0409 0.0290 0.0928 0.0629 0.0236 0.0323 0.0604 0.0627 0.0241 0.0151 0.0670 0.0857 0.0218 0.0186 0.0639 0.0644 0.0315 0.0231 0.0655 0.0699 0.0244 0.0250 0.0779 0.1043 0.0352 0.0233 0.0747 0.1096 0.0355 0.0441 0.0647 0.0907 0.0538 0.0314 0.0682 0.1043 0.0243 0.0170 0.0664 0.0735 0.0314 0.0204 0.0660 0.0840 0.0361 0.0682 0.0930 0.0860 0.0729 0.0329 0.0811 0.0964 0.0388 0.0389 0.0724 0.0469 0.0397 0.0231 0.0887 0.0652 0.0330 0.0419 0.1259 0.0752 0.0550 0.0340 0.1075 0.0646 0.0336 0.0555 0.0705 0.0680 0.0363 0.0233 0.0736 0.0903 0.0293 0.0197 0.0725 0.0822 0.0423 0.0275 0.0703 0.0810 0.0294 0.0429 0.1062 0.1407 0.0522 0.0425 0.1122 0.1442 0.0402 0.0641 0.0703 0.1164 0.0723 0.0476 0.0641 0.1520 0.0296 0.0293 0.0734 0.0848 0.0521 0.0356 0.0992 0.0993 0.0463 0.1055 0.1134 0.1091 0.1000 0.0488 0.0907 0.1203 0.0476 0.0519 0.0596 0.0367 0.0479 0.0300 0.0997 0.0665 0.0351 0.0570 0.0796 0.0734 0.0731 0.0489 0.1103 0.0587 0.0428 0.0666 0.0947 0.0714 0.0498 0.0428 0.0891 0.0701 0.0338 0.0260 0.0690 0.0999 0.0530 0.0396 0.0724 0.0688 0.0585 0.0534 0.1691 0.1490 0.0800 0.0878 0.1869 0.1216 0.0396 0.0868 0.0932 0.1090 0.0997 0.0875 0.0734 0.1633 0.0444 0.0473 0.0741 0.0897 0.0646 0.0599 0.1342 0.1003 0.0581 0.1543 0.1193 0.1226 0.1366 0.0825 0.0969 0.1248 0.0224 0.0236 0.0771 0.0618 0.0238 0.0143 0.0959 0.0890 0.0224 0.0283 0.1029 0.0788 0.0399 0.0279 0.1084 0.0750 0.0238 0.0314 0.0663 0.0786 0.0248 0.0146 0.0765 0.1106 0.0232 0.0184 0.0715 0.0772 0.0313 0.0233 0.0796 0.0836 0.0255 0.0246 0.0829 0.1299 0.0371 0.0216 0.0815 0.1361 0.0384 0.0433 0.0724 0.1077 0.0543 0.0319 0.0836 0.1223 0.0250 0.0164 0.0717 0.0918 0.0326 0.0199 0.0750 0.1076 0.0376 0.0671 0.1017 0.1027 0.0732 0.0331 0.0959 0.1147 0.0354 0.0361 0.0797 0.0569 0.0376 0.0212 0.1003 0.0825 0.0330 0.0396 0.1386 0.0910 0.0509 0.0333 0.1239 0.0734 0.0332 0.0487 0.0749 0.0775 0.0345 0.0205 0.0783 0.1084 0.0292 0.0180 0.0837 0.0929 0.0383 0.0280 0.0842 0.0912 0.0305 0.0398 0.1106 0.1616 0.0522 0.0366 0.1116 0.1627 0.0421 0.0616 0.0762 0.1291 0.0677 0.0489 0.0779 0.1663 0.0292 0.0270 0.0787 0.0987 0.0525 0.0329 0.1052 0.1164 0.0464 0.0996 0.1240 0.1203 0.0927 0.0474 0.1033 0.1339 0.0401 0.0418 0.0615 0.0457 0.0450 0.0273 0.1065 0.0816 0.0334 0.0504 0.0853 0.0712 0.0657 0.0486 0.1221 0.0601 0.0397 0.0534 0.0971 0.0778 0.0451 0.0328 0.0903 0.0778 0.0307 0.0244 0.0760 0.1010 0.0489 0.0408 0.0799 0.0670 0.0568 0.0483 0.1714 0.1564 0.0758 0.0684 0.1765 0.1279 0.0340 0.0794 0.0961 0.1040 0.0894 0.0865 0.0781 0.1615 0.0400 0.0404 0.0767 0.0898 0.0603 0.0528 0.1343 0.1084 0.0539 0.1381 0.1299 0.1128 0.1205 0.0803 0.1017 0.1229 0.0229 0.0237 0.1041 0.1017 0.0255 0.0155 0.1290 0.1303 0.0239 0.0283 0.1504 0.1513 0.0401 0.0289 0.1596 0.1247 0.0264 0.0327 0.0865 0.1281 0.0263 0.0164 0.0989 0.1574 0.0258 0.0187 0.1049 0.1492 0.0342 0.0233 0.1271 0.1453 0.0288 0.0261 0.1023 0.2062 0.0402 0.0222 0.0977 0.1857 0.0435 0.0438 0.1065 0.1981 0.0588 0.0338 0.1375 0.2011 0.0276 0.0174 0.0935 0.1462 0.0353 0.0203 0.0957 0.1518 0.0404 0.0677 0.1492 0.1857 0.0745 0.0341 0.1490 0.1923 0.0357 0.0344 0.0988 0.0895 0.0387 0.0233 0.1306 0.1110 0.0338 0.0374 0.1869 0.1411 0.0477 0.0347 0.1750 0.1164 0.0359 0.0479 0.0874 0.1174 0.0355 0.0231 0.0931 0.1323 0.0332 0.0179 0.1124 0.1535 0.0391 0.0285 0.1252 0.1428 0.0338 0.0386 0.1283 0.2078 0.0553 0.0346 0.1240 0.1910 0.0473 0.0584 0.1033 0.2224 0.0685 0.0533 0.1347 0.2383 0.0319 0.0273 0.0964 0.1312 0.0555 0.0318 0.1324 0.1464 0.0474 0.0943 0.1599 0.1894 0.0879 0.0522 0.1541 0.1963 0.0390 0.0351 0.0691 0.0595 0.0443 0.0244 0.1247 0.1096 0.0327 0.0432 0.1075 0.1145 0.0595 0.0519 0.1609 0.0961 0.0398 0.0454 0.1075 0.0828 0.0439 0.0282 0.1060 0.0984 0.0371 0.0233 0.0935 0.1630 0.0466 0.0417 0.0802 0.1021 0.0541 0.0420 0.1809 0.1346 0.0759 0.0564 0.1908 0.1325 0.0362 0.0704 0.1278 0.1838 0.0833 0.0917 0.0859 0.2116 0.0401 0.0352 0.0852 0.0706 0.0594 0.0450 0.1540 0.1143 0.0518 0.1173 0.1497 0.1642 0.1014 0.0866 0.1340 0.1704 2 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os.path 3 | 4 | from parameterized import parameterized 5 | from memory_profiler import LineProfiler 6 | import numpy as np 7 | 8 | import gist 9 | 10 | 11 | DATADIR = os.path.join(os.path.dirname(__file__), 'test/data') 12 | 13 | 14 | class FunctionalityTestCase(unittest.TestCase): 15 | def test_with_zero_array(self): 16 | black_image = np.zeros((480, 640, 3), dtype=np.uint8) 17 | gist.extract(black_image) 18 | 19 | @parameterized.expand([ 20 | ((), ), 21 | ((0, 0, 3), ), # Both width and height are 0 22 | ((0, 32, 3), ), # Width is 0 23 | ((32, 0, 3), ), # Height is 0 24 | ((32, 32, 0), ), # Invalid color channels 25 | ((32, 32, 1), ), # Invalid color channels 26 | ((32, 32, 2), ), # Invalid color channels 27 | ((32, 32, 4), ), # Invalid color channels 28 | ]) 29 | def test_with_invalid_size_array(self, shape): 30 | arr = np.zeros(shape, dtype=np.uint8) 31 | with self.assertRaises(ValueError): 32 | gist.extract(arr) 33 | 34 | def test_with_None(self): 35 | with self.assertRaises(TypeError): 36 | self.assertIsNone(gist.extract(None)) 37 | 38 | 39 | class ValueTestCase(unittest.TestCase): 40 | def load_npy(self, relpath): 41 | return np.load(os.path.join(DATADIR, relpath)) 42 | 43 | def load_reference(self, path): 44 | with open(path) as f: 45 | content = f.read() 46 | 47 | arr = np.array([float(elem) for elem in content.split()]) 48 | return arr 49 | 50 | def test(self): 51 | arr = self.load_npy('scene.npy') 52 | result = gist.extract(arr) 53 | 54 | reference = self.load_reference( 55 | os.path.join(DATADIR, 'scene.no_arg.result')) 56 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 57 | 58 | def test_with_nblocks_2_as_positional_argument(self): 59 | arr = self.load_npy('scene.npy') 60 | result = gist.extract(arr, 2) 61 | 62 | reference = self.load_reference( 63 | os.path.join(DATADIR, 'scene.nblocks2.result')) 64 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 65 | 66 | def test_with_nblocks_4_as_positional_argument(self): 67 | arr = self.load_npy('scene.npy') 68 | result = gist.extract(arr, 4) 69 | 70 | reference = self.load_reference( 71 | os.path.join(DATADIR, 'scene.nblocks4.result')) 72 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 73 | 74 | def test_with_nblocks_2_as_keyword_argument(self): 75 | arr = self.load_npy('scene.npy') 76 | result = gist.extract(arr, nblocks=2) 77 | 78 | reference = self.load_reference( 79 | os.path.join(DATADIR, 'scene.nblocks2.result')) 80 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 81 | 82 | def test_with_nblocks_4_as_keyword_argument(self): 83 | arr = self.load_npy('scene.npy') 84 | result = gist.extract(arr, nblocks=4) 85 | 86 | reference = self.load_reference( 87 | os.path.join(DATADIR, 'scene.nblocks4.result')) 88 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 89 | 90 | def test_with_orientations_per_scale_4_4_4_as_keyword_argument(self): 91 | arr = self.load_npy('scene.npy') 92 | result = gist.extract(arr, orientations_per_scale=(4, 4, 4)) 93 | 94 | reference = self.load_reference( 95 | os.path.join(DATADIR, 'scene.ops_4_4_4.result')) 96 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 97 | 98 | def test_with_orientations_per_scale_8_8_8_as_keyword_argument(self): 99 | arr = self.load_npy('scene.npy') 100 | result = gist.extract(arr, orientations_per_scale=(8, 8, 8)) 101 | 102 | reference = self.load_reference( 103 | os.path.join(DATADIR, 'scene.ops_8_8_8.result')) 104 | np.testing.assert_allclose(reference, result, rtol=1e-04, atol=1e-04) 105 | 106 | 107 | class MemoryUsageTestCase(unittest.TestCase): 108 | def load_npy(self, relpath): 109 | return np.load(os.path.join(DATADIR, relpath)) 110 | 111 | def test(self): 112 | def run(img): 113 | gist.extract(img) 114 | gist.extract(img) 115 | gist.extract(img) 116 | gist.extract(img) 117 | gist.extract(img) 118 | 119 | img = self.load_npy('scene_640.npy') 120 | img_mb_as_float = img.shape[0] * img.shape[1] * img.shape[2] * 4 / 1024 / 1024 121 | 122 | prof = LineProfiler() 123 | run = prof(run) 124 | run(img) 125 | 126 | _, lines = list(prof.code_map.items())[0] 127 | mem_list = [mem for lineo, mem in list(lines)] 128 | mem_inc_list = [inc for inc, mem in mem_list[1:]] # First line of `run` function is definition ("def run (img):") 129 | mem_inc_list[1:] # Ignore the first because it includes an overhead of loading module. 130 | 131 | for mem_inc in mem_inc_list: 132 | # Assert that at least the memory used for the loaded image is released. 133 | self.assertTrue(mem_inc < img_mb_as_float) 134 | 135 | 136 | if __name__ == '__main__': 137 | unittest.main() 138 | -------------------------------------------------------------------------------- /gistmodule.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "lear_gist-1.2/gist.h" 7 | 8 | struct module_state { 9 | PyObject *error; 10 | }; 11 | 12 | #if PY_MAJOR_VERSION >= 3 13 | #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) 14 | #else 15 | #define GETSTATE(m) (&_state) 16 | static struct module_state _state; 17 | #endif 18 | 19 | static PyObject* gist_extract(PyObject *self, PyObject *args, PyObject *keywds) 20 | { 21 | PyArrayObject *image; // Python object to contain the given `image` argument. 22 | PyObject* pyobj_orientations_per_scale = NULL; // Python Object to contain the given `orientations_per_scale` argument. 23 | int nblocks=4; // An variable to contain the given `nblocks` argument, whose default value is 4 24 | 25 | // n_scale and orientations_per_scale are parsed from pyobj_orientations_per_scale below. 26 | int n_scale; 27 | int *orientations_per_scale = NULL; 28 | 29 | // Parse the given arguments 30 | static char *kwlist[] = {"", "nblocks", "orientations_per_scale", NULL}; 31 | if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|iO", kwlist, 32 | &PyArray_Type, &image, &nblocks, &pyobj_orientations_per_scale)) 33 | { 34 | return NULL; 35 | } 36 | 37 | // Check validity of image argument 38 | if (PyArray_TYPE(image) != NPY_UINT8) { 39 | PyErr_SetString(PyExc_ValueError, "type of image must be uint8"); 40 | return NULL; 41 | } 42 | 43 | if (PyArray_NDIM(image) != 3) { 44 | PyErr_SetString(PyExc_ValueError, "dimensions of image must be 3."); 45 | return NULL; 46 | } 47 | 48 | // Parse orientations_per_scale argument 49 | // Ref: https://www.oreilly.com/library/view/python-cookbook/0596001673/ch16s03.html 50 | if (pyobj_orientations_per_scale != NULL) { 51 | pyobj_orientations_per_scale = PySequence_Fast(pyobj_orientations_per_scale, "orientations_per_scale must be iterable"); 52 | if (!pyobj_orientations_per_scale) { 53 | return NULL; 54 | } 55 | 56 | n_scale = PySequence_Fast_GET_SIZE(pyobj_orientations_per_scale); 57 | orientations_per_scale = malloc(n_scale * sizeof(int)); 58 | if (!orientations_per_scale) { 59 | Py_DECREF(pyobj_orientations_per_scale); 60 | return PyErr_NoMemory(); 61 | } 62 | 63 | for (int i = 0; i < n_scale; ++i) { 64 | PyObject *long_item; 65 | PyObject *item = PySequence_Fast_GET_ITEM(pyobj_orientations_per_scale, i); 66 | if (!item) { 67 | Py_DECREF(pyobj_orientations_per_scale); 68 | free(orientations_per_scale); 69 | return NULL; 70 | } 71 | long_item = PyNumber_Long(item); 72 | if (!long_item) { 73 | Py_DECREF(pyobj_orientations_per_scale); 74 | free(orientations_per_scale); 75 | PyErr_SetString(PyExc_TypeError, "all items of orientations_per_scale must be int"); 76 | return NULL; 77 | } 78 | orientations_per_scale[i] = (int) PyLong_AsLong(long_item); // XXX: Down cast 79 | Py_DECREF(long_item); 80 | } 81 | 82 | Py_DECREF(pyobj_orientations_per_scale); 83 | } else { 84 | // Default values of n_scale and orientations_per_scale 85 | n_scale = 3; 86 | orientations_per_scale = malloc(n_scale * sizeof(int)); 87 | orientations_per_scale[0] = 8; 88 | orientations_per_scale[1] = 8; 89 | orientations_per_scale[2] = 4; 90 | } 91 | 92 | npy_intp *dims_image = PyArray_DIMS(image); 93 | 94 | const int w = (int) *(dims_image+1); 95 | const int h = (int) *(dims_image); 96 | const int channels = (int) *(dims_image+2); 97 | 98 | if (w == 0 || h == 0) { 99 | PyErr_SetString(PyExc_ValueError, "invalid image size."); 100 | return NULL; 101 | } 102 | if (channels != 3) { 103 | PyErr_SetString(PyExc_ValueError, "invalid color channels."); 104 | return NULL; 105 | } 106 | 107 | // Read image to color_image_t structure 108 | color_image_t *im=color_image_new(w,h); 109 | 110 | for (int y=0, i=0 ; yc1[i] = *(unsigned char *)PyArray_GETPTR3(image, y, x, 0); 113 | im->c2[i] = *(unsigned char *)PyArray_GETPTR3(image, y, x, 1); 114 | im->c3[i] = *(unsigned char *)PyArray_GETPTR3(image, y, x, 2); 115 | } 116 | } 117 | 118 | // Extract descriptor 119 | float *desc=color_gist_scaletab(im, nblocks, n_scale, orientations_per_scale); 120 | 121 | /* compute descriptor size */ 122 | int descsize=0; 123 | for(int i=0;i= 3 147 | 148 | static int gist_traverse(PyObject *m, visitproc visit, void *arg) { 149 | Py_VISIT(GETSTATE(m)->error); 150 | return 0; 151 | } 152 | 153 | static int gist_clear(PyObject *m) { 154 | Py_CLEAR(GETSTATE(m)->error); 155 | return 0; 156 | } 157 | 158 | 159 | static struct PyModuleDef moduledef = { 160 | PyModuleDef_HEAD_INIT, 161 | "gist", 162 | NULL, 163 | sizeof(struct module_state), 164 | gist_methods, 165 | NULL, 166 | gist_traverse, 167 | gist_clear, 168 | NULL 169 | }; 170 | 171 | #define INITERROR return NULL 172 | 173 | PyMODINIT_FUNC 174 | PyInit_gist(void) 175 | 176 | #else 177 | #define INITERROR return 178 | 179 | PyMODINIT_FUNC 180 | initgist(void) 181 | #endif 182 | { 183 | #if PY_MAJOR_VERSION >= 3 184 | PyObject *module = PyModule_Create(&moduledef); 185 | #else 186 | PyObject *module = Py_InitModule("gist", gist_methods); 187 | #endif 188 | 189 | if (module == NULL) 190 | INITERROR; 191 | struct module_state *st = GETSTATE(module); 192 | 193 | st->error = PyErr_NewException("gist.Error", NULL, NULL); 194 | if (st->error == NULL) { 195 | Py_DECREF(module); 196 | INITERROR; 197 | } 198 | 199 | import_array(); 200 | 201 | #if PY_MAJOR_VERSION >= 3 202 | return module; 203 | #endif 204 | } 205 | -------------------------------------------------------------------------------- /test/data/scene.nblocks4.result: -------------------------------------------------------------------------------- 1 | 0.0181 0.0186 0.0561 0.0348 0.0178 0.0088 0.0704 0.0495 0.0129 0.0130 0.0675 0.0456 0.0290 0.0247 0.0691 0.0404 0.0191 0.0207 0.0432 0.0348 0.0131 0.0073 0.0532 0.0490 0.0126 0.0121 0.0538 0.0395 0.0228 0.0174 0.0495 0.0393 0.0168 0.0236 0.0382 0.0391 0.0155 0.0100 0.0389 0.0586 0.0139 0.0135 0.0407 0.0462 0.0206 0.0153 0.0398 0.0465 0.0164 0.0212 0.0450 0.0521 0.0212 0.0121 0.0467 0.0698 0.0191 0.0132 0.0420 0.0501 0.0255 0.0158 0.0467 0.0575 0.0188 0.0179 0.0656 0.0875 0.0277 0.0159 0.0593 0.0881 0.0281 0.0192 0.0423 0.0675 0.0339 0.0248 0.0519 0.0801 0.0198 0.0141 0.0461 0.0689 0.0238 0.0183 0.0444 0.0725 0.0277 0.0485 0.0534 0.0744 0.0477 0.0247 0.0432 0.0810 0.0188 0.0107 0.0413 0.0453 0.0213 0.0115 0.0363 0.0551 0.0275 0.0562 0.0662 0.0585 0.0619 0.0240 0.0507 0.0669 0.0156 0.0130 0.0538 0.0332 0.0203 0.0120 0.0547 0.0493 0.0201 0.0267 0.0783 0.0524 0.0358 0.0220 0.0759 0.0517 0.0282 0.0315 0.0581 0.0342 0.0322 0.0150 0.0751 0.0445 0.0205 0.0190 0.0953 0.0487 0.0327 0.0287 0.0776 0.0401 0.0321 0.0335 0.0371 0.0284 0.0215 0.0124 0.0479 0.0454 0.0151 0.0131 0.0581 0.0508 0.0259 0.0222 0.0622 0.0457 0.0250 0.0449 0.0366 0.0347 0.0212 0.0140 0.0408 0.0562 0.0193 0.0127 0.0520 0.0532 0.0321 0.0218 0.0449 0.0503 0.0174 0.0335 0.0627 0.0640 0.0327 0.0180 0.0576 0.0778 0.0257 0.0150 0.0429 0.0702 0.0311 0.0186 0.0453 0.0604 0.0284 0.0297 0.0928 0.1272 0.0367 0.0301 0.0912 0.1183 0.0321 0.0282 0.0457 0.0945 0.0404 0.0373 0.0471 0.1153 0.0239 0.0265 0.0544 0.0922 0.0353 0.0335 0.0770 0.1050 0.0288 0.0698 0.0584 0.0899 0.0612 0.0390 0.0433 0.1230 0.0245 0.0189 0.0431 0.0434 0.0375 0.0193 0.0545 0.0583 0.0360 0.0907 0.0749 0.0737 0.0851 0.0355 0.0538 0.0630 0.0219 0.0256 0.0534 0.0364 0.0343 0.0202 0.0696 0.0461 0.0315 0.0416 0.1118 0.0615 0.0511 0.0329 0.0894 0.0515 0.0476 0.0519 0.0596 0.0367 0.0479 0.0300 0.0997 0.0665 0.0351 0.0570 0.0796 0.0734 0.0731 0.0489 0.1103 0.0587 0.0428 0.0666 0.0947 0.0714 0.0498 0.0428 0.0891 0.0701 0.0338 0.0260 0.0690 0.0999 0.0530 0.0396 0.0724 0.0688 0.0585 0.0534 0.1691 0.1490 0.0800 0.0878 0.1869 0.1216 0.0396 0.0868 0.0932 0.1090 0.0997 0.0875 0.0734 0.1633 0.0444 0.0473 0.0741 0.0897 0.0646 0.0599 0.1342 0.1003 0.0581 0.1543 0.1193 0.1226 0.1366 0.0825 0.0969 0.1248 0.0175 0.0185 0.0616 0.0447 0.0180 0.0093 0.0831 0.0660 0.0137 0.0132 0.0763 0.0545 0.0283 0.0235 0.0806 0.0486 0.0191 0.0200 0.0483 0.0430 0.0136 0.0077 0.0631 0.0653 0.0131 0.0119 0.0603 0.0477 0.0230 0.0173 0.0582 0.0465 0.0176 0.0221 0.0429 0.0501 0.0162 0.0102 0.0460 0.0770 0.0149 0.0135 0.0457 0.0563 0.0208 0.0156 0.0492 0.0562 0.0167 0.0208 0.0490 0.0656 0.0220 0.0112 0.0533 0.0890 0.0203 0.0135 0.0472 0.0596 0.0260 0.0160 0.0578 0.0695 0.0194 0.0183 0.0693 0.1093 0.0296 0.0143 0.0641 0.1086 0.0307 0.0188 0.0481 0.0800 0.0339 0.0255 0.0637 0.0931 0.0215 0.0131 0.0500 0.0858 0.0243 0.0178 0.0491 0.0903 0.0292 0.0475 0.0596 0.0887 0.0485 0.0251 0.0523 0.0953 0.0196 0.0099 0.0444 0.0573 0.0223 0.0114 0.0422 0.0726 0.0285 0.0552 0.0712 0.0717 0.0627 0.0240 0.0606 0.0808 0.0160 0.0131 0.0590 0.0422 0.0210 0.0118 0.0653 0.0642 0.0207 0.0265 0.0848 0.0632 0.0353 0.0222 0.0885 0.0626 0.0255 0.0298 0.0641 0.0422 0.0307 0.0144 0.0853 0.0571 0.0216 0.0195 0.1043 0.0600 0.0314 0.0297 0.0914 0.0468 0.0308 0.0295 0.0396 0.0342 0.0205 0.0113 0.0540 0.0588 0.0148 0.0119 0.0675 0.0635 0.0236 0.0224 0.0700 0.0509 0.0247 0.0380 0.0399 0.0404 0.0198 0.0128 0.0459 0.0702 0.0194 0.0121 0.0599 0.0609 0.0289 0.0215 0.0546 0.0574 0.0169 0.0302 0.0670 0.0725 0.0319 0.0153 0.0603 0.0866 0.0255 0.0147 0.0483 0.0770 0.0291 0.0195 0.0564 0.0697 0.0282 0.0300 0.0956 0.1482 0.0388 0.0248 0.0899 0.1340 0.0339 0.0278 0.0500 0.1071 0.0390 0.0393 0.0586 0.1257 0.0251 0.0235 0.0588 0.1057 0.0340 0.0305 0.0759 0.1126 0.0296 0.0669 0.0645 0.0970 0.0560 0.0391 0.0485 0.1328 0.0237 0.0170 0.0463 0.0502 0.0390 0.0183 0.0596 0.0728 0.0357 0.0850 0.0823 0.0808 0.0803 0.0339 0.0613 0.0741 0.0206 0.0245 0.0587 0.0429 0.0336 0.0181 0.0811 0.0594 0.0315 0.0393 0.1206 0.0718 0.0472 0.0318 0.1026 0.0597 0.0401 0.0418 0.0615 0.0457 0.0450 0.0273 0.1065 0.0816 0.0334 0.0504 0.0853 0.0712 0.0657 0.0486 0.1221 0.0601 0.0397 0.0534 0.0971 0.0778 0.0451 0.0328 0.0903 0.0778 0.0307 0.0244 0.0760 0.1010 0.0489 0.0408 0.0799 0.0670 0.0568 0.0483 0.1714 0.1564 0.0758 0.0684 0.1765 0.1279 0.0340 0.0794 0.0961 0.1040 0.0894 0.0865 0.0781 0.1615 0.0400 0.0404 0.0767 0.0898 0.0603 0.0528 0.1343 0.1084 0.0539 0.1381 0.1299 0.1128 0.1205 0.0803 0.1017 0.1229 0.0189 0.0179 0.0848 0.0733 0.0198 0.0104 0.1112 0.0981 0.0150 0.0131 0.1118 0.1126 0.0302 0.0253 0.1163 0.0780 0.0206 0.0203 0.0646 0.0696 0.0156 0.0090 0.0871 0.0969 0.0150 0.0122 0.0882 0.0931 0.0259 0.0173 0.0852 0.0800 0.0199 0.0234 0.0582 0.0837 0.0182 0.0118 0.0611 0.1118 0.0172 0.0141 0.0675 0.1112 0.0246 0.0152 0.0805 0.1018 0.0194 0.0215 0.0615 0.1036 0.0235 0.0121 0.0665 0.1227 0.0233 0.0133 0.0728 0.1169 0.0299 0.0162 0.0968 0.1222 0.0217 0.0194 0.0840 0.1734 0.0326 0.0151 0.0746 0.1495 0.0351 0.0190 0.0728 0.1494 0.0381 0.0274 0.1044 0.1538 0.0241 0.0141 0.0650 0.1342 0.0262 0.0176 0.0614 0.1243 0.0319 0.0486 0.0868 0.1612 0.0515 0.0262 0.0911 0.1601 0.0237 0.0110 0.0590 0.0934 0.0245 0.0117 0.0571 0.1049 0.0309 0.0554 0.1068 0.1323 0.0639 0.0247 0.0970 0.1379 0.0186 0.0133 0.0788 0.0709 0.0229 0.0126 0.0860 0.0939 0.0232 0.0262 0.1251 0.1221 0.0365 0.0234 0.1325 0.1049 0.0262 0.0280 0.0806 0.0649 0.0320 0.0168 0.1091 0.0778 0.0213 0.0186 0.1378 0.0995 0.0316 0.0330 0.1337 0.0735 0.0319 0.0286 0.0498 0.0581 0.0224 0.0140 0.0741 0.0804 0.0155 0.0121 0.0866 0.1067 0.0266 0.0223 0.0901 0.0923 0.0272 0.0387 0.0465 0.0738 0.0220 0.0160 0.0554 0.0887 0.0243 0.0138 0.0790 0.1102 0.0300 0.0208 0.0844 0.1010 0.0192 0.0284 0.0751 0.0991 0.0331 0.0157 0.0674 0.1009 0.0272 0.0129 0.0758 0.1230 0.0319 0.0200 0.0984 0.0981 0.0298 0.0292 0.1095 0.1833 0.0422 0.0237 0.0964 0.1581 0.0389 0.0262 0.0655 0.1879 0.0427 0.0431 0.0990 0.1795 0.0268 0.0214 0.0742 0.1377 0.0367 0.0285 0.0920 0.1311 0.0331 0.0652 0.0779 0.1649 0.0540 0.0436 0.0942 0.2015 0.0280 0.0183 0.0591 0.0683 0.0410 0.0179 0.0786 0.0997 0.0360 0.0795 0.0979 0.1277 0.0751 0.0371 0.0873 0.1036 0.0225 0.0249 0.0747 0.0662 0.0347 0.0187 0.1072 0.0770 0.0329 0.0371 0.1675 0.1117 0.0458 0.0358 0.1450 0.0830 0.0390 0.0351 0.0691 0.0595 0.0443 0.0244 0.1247 0.1096 0.0327 0.0432 0.1075 0.1145 0.0595 0.0519 0.1609 0.0961 0.0398 0.0454 0.1075 0.0828 0.0439 0.0282 0.1060 0.0984 0.0371 0.0233 0.0935 0.1630 0.0466 0.0417 0.0802 0.1021 0.0541 0.0420 0.1809 0.1346 0.0759 0.0564 0.1908 0.1325 0.0362 0.0704 0.1278 0.1838 0.0833 0.0917 0.0859 0.2116 0.0401 0.0352 0.0852 0.0706 0.0594 0.0450 0.1540 0.1143 0.0518 0.1173 0.1497 0.1642 0.1014 0.0866 0.1340 0.1704 2 | -------------------------------------------------------------------------------- /test/data/scene.no_arg.result: -------------------------------------------------------------------------------- 1 | 0.0181 0.0186 0.0561 0.0348 0.0178 0.0088 0.0704 0.0495 0.0129 0.0130 0.0675 0.0456 0.0290 0.0247 0.0691 0.0404 0.0191 0.0207 0.0432 0.0348 0.0131 0.0073 0.0532 0.0490 0.0126 0.0121 0.0538 0.0395 0.0228 0.0174 0.0495 0.0393 0.0168 0.0236 0.0382 0.0391 0.0155 0.0100 0.0389 0.0586 0.0139 0.0135 0.0407 0.0462 0.0206 0.0153 0.0398 0.0465 0.0164 0.0212 0.0450 0.0521 0.0212 0.0121 0.0467 0.0698 0.0191 0.0132 0.0420 0.0501 0.0255 0.0158 0.0467 0.0575 0.0188 0.0179 0.0656 0.0875 0.0277 0.0159 0.0593 0.0881 0.0281 0.0192 0.0423 0.0675 0.0339 0.0248 0.0519 0.0801 0.0198 0.0141 0.0461 0.0689 0.0238 0.0183 0.0444 0.0725 0.0277 0.0485 0.0534 0.0744 0.0477 0.0247 0.0432 0.0810 0.0188 0.0107 0.0413 0.0453 0.0213 0.0115 0.0363 0.0551 0.0275 0.0562 0.0662 0.0585 0.0619 0.0240 0.0507 0.0669 0.0156 0.0130 0.0538 0.0332 0.0203 0.0120 0.0547 0.0493 0.0201 0.0267 0.0783 0.0524 0.0358 0.0220 0.0759 0.0517 0.0282 0.0315 0.0581 0.0342 0.0322 0.0150 0.0751 0.0445 0.0205 0.0190 0.0953 0.0487 0.0327 0.0287 0.0776 0.0401 0.0321 0.0335 0.0371 0.0284 0.0215 0.0124 0.0479 0.0454 0.0151 0.0131 0.0581 0.0508 0.0259 0.0222 0.0622 0.0457 0.0250 0.0449 0.0366 0.0347 0.0212 0.0140 0.0408 0.0562 0.0193 0.0127 0.0520 0.0532 0.0321 0.0218 0.0449 0.0503 0.0174 0.0335 0.0627 0.0640 0.0327 0.0180 0.0576 0.0778 0.0257 0.0150 0.0429 0.0702 0.0311 0.0186 0.0453 0.0604 0.0284 0.0297 0.0928 0.1272 0.0367 0.0301 0.0912 0.1183 0.0321 0.0282 0.0457 0.0945 0.0404 0.0373 0.0471 0.1153 0.0239 0.0265 0.0544 0.0922 0.0353 0.0335 0.0770 0.1050 0.0288 0.0698 0.0584 0.0899 0.0612 0.0390 0.0433 0.1230 0.0245 0.0189 0.0431 0.0434 0.0375 0.0193 0.0545 0.0583 0.0360 0.0907 0.0749 0.0737 0.0851 0.0355 0.0538 0.0630 0.0219 0.0256 0.0534 0.0364 0.0343 0.0202 0.0696 0.0461 0.0315 0.0416 0.1118 0.0615 0.0511 0.0329 0.0894 0.0515 0.0476 0.0519 0.0596 0.0367 0.0479 0.0300 0.0997 0.0665 0.0351 0.0570 0.0796 0.0734 0.0731 0.0489 0.1103 0.0587 0.0428 0.0666 0.0947 0.0714 0.0498 0.0428 0.0891 0.0701 0.0338 0.0260 0.0690 0.0999 0.0530 0.0396 0.0724 0.0688 0.0585 0.0534 0.1691 0.1490 0.0800 0.0878 0.1869 0.1216 0.0396 0.0868 0.0932 0.1090 0.0997 0.0875 0.0734 0.1633 0.0444 0.0473 0.0741 0.0897 0.0646 0.0599 0.1342 0.1003 0.0581 0.1543 0.1193 0.1226 0.1366 0.0825 0.0969 0.1248 0.0175 0.0185 0.0616 0.0447 0.0180 0.0093 0.0831 0.0660 0.0137 0.0132 0.0763 0.0545 0.0283 0.0235 0.0806 0.0486 0.0191 0.0200 0.0483 0.0430 0.0136 0.0077 0.0631 0.0653 0.0131 0.0119 0.0603 0.0477 0.0230 0.0173 0.0582 0.0465 0.0176 0.0221 0.0429 0.0501 0.0162 0.0102 0.0460 0.0770 0.0149 0.0135 0.0457 0.0563 0.0208 0.0156 0.0492 0.0562 0.0167 0.0208 0.0490 0.0656 0.0220 0.0112 0.0533 0.0890 0.0203 0.0135 0.0472 0.0596 0.0260 0.0160 0.0578 0.0695 0.0194 0.0183 0.0693 0.1093 0.0296 0.0143 0.0641 0.1086 0.0307 0.0188 0.0481 0.0800 0.0339 0.0255 0.0637 0.0931 0.0215 0.0131 0.0500 0.0858 0.0243 0.0178 0.0491 0.0903 0.0292 0.0475 0.0596 0.0887 0.0485 0.0251 0.0523 0.0953 0.0196 0.0099 0.0444 0.0573 0.0223 0.0114 0.0422 0.0726 0.0285 0.0552 0.0712 0.0717 0.0627 0.0240 0.0606 0.0808 0.0160 0.0131 0.0590 0.0422 0.0210 0.0118 0.0653 0.0642 0.0207 0.0265 0.0848 0.0632 0.0353 0.0222 0.0885 0.0626 0.0255 0.0298 0.0641 0.0422 0.0307 0.0144 0.0853 0.0571 0.0216 0.0195 0.1043 0.0600 0.0314 0.0297 0.0914 0.0468 0.0308 0.0295 0.0396 0.0342 0.0205 0.0113 0.0540 0.0588 0.0148 0.0119 0.0675 0.0635 0.0236 0.0224 0.0700 0.0509 0.0247 0.0380 0.0399 0.0404 0.0198 0.0128 0.0459 0.0702 0.0194 0.0121 0.0599 0.0609 0.0289 0.0215 0.0546 0.0574 0.0169 0.0302 0.0670 0.0725 0.0319 0.0153 0.0603 0.0866 0.0255 0.0147 0.0483 0.0770 0.0291 0.0195 0.0564 0.0697 0.0282 0.0300 0.0956 0.1482 0.0388 0.0248 0.0899 0.1340 0.0339 0.0278 0.0500 0.1071 0.0390 0.0393 0.0586 0.1257 0.0251 0.0235 0.0588 0.1057 0.0340 0.0305 0.0759 0.1126 0.0296 0.0669 0.0645 0.0970 0.0560 0.0391 0.0485 0.1328 0.0237 0.0170 0.0463 0.0502 0.0390 0.0183 0.0596 0.0728 0.0357 0.0850 0.0823 0.0808 0.0803 0.0339 0.0613 0.0741 0.0206 0.0245 0.0587 0.0429 0.0336 0.0181 0.0811 0.0594 0.0315 0.0393 0.1206 0.0718 0.0472 0.0318 0.1026 0.0597 0.0401 0.0418 0.0615 0.0457 0.0450 0.0273 0.1065 0.0816 0.0334 0.0504 0.0853 0.0712 0.0657 0.0486 0.1221 0.0601 0.0397 0.0534 0.0971 0.0778 0.0451 0.0328 0.0903 0.0778 0.0307 0.0244 0.0760 0.1010 0.0489 0.0408 0.0799 0.0670 0.0568 0.0483 0.1714 0.1564 0.0758 0.0684 0.1765 0.1279 0.0340 0.0794 0.0961 0.1040 0.0894 0.0865 0.0781 0.1615 0.0400 0.0404 0.0767 0.0898 0.0603 0.0528 0.1343 0.1084 0.0539 0.1381 0.1299 0.1128 0.1205 0.0803 0.1017 0.1229 0.0189 0.0179 0.0848 0.0733 0.0198 0.0104 0.1112 0.0981 0.0150 0.0131 0.1118 0.1126 0.0302 0.0253 0.1163 0.0780 0.0206 0.0203 0.0646 0.0696 0.0156 0.0090 0.0871 0.0969 0.0150 0.0122 0.0882 0.0931 0.0259 0.0173 0.0852 0.0800 0.0199 0.0234 0.0582 0.0837 0.0182 0.0118 0.0611 0.1118 0.0172 0.0141 0.0675 0.1112 0.0246 0.0152 0.0805 0.1018 0.0194 0.0215 0.0615 0.1036 0.0235 0.0121 0.0665 0.1227 0.0233 0.0133 0.0728 0.1169 0.0299 0.0162 0.0968 0.1222 0.0217 0.0194 0.0840 0.1734 0.0326 0.0151 0.0746 0.1495 0.0351 0.0190 0.0728 0.1494 0.0381 0.0274 0.1044 0.1538 0.0241 0.0141 0.0650 0.1342 0.0262 0.0176 0.0614 0.1243 0.0319 0.0486 0.0868 0.1612 0.0515 0.0262 0.0911 0.1601 0.0237 0.0110 0.0590 0.0934 0.0245 0.0117 0.0571 0.1049 0.0309 0.0554 0.1068 0.1323 0.0639 0.0247 0.0970 0.1379 0.0186 0.0133 0.0788 0.0709 0.0229 0.0126 0.0860 0.0939 0.0232 0.0262 0.1251 0.1221 0.0365 0.0234 0.1325 0.1049 0.0262 0.0280 0.0806 0.0649 0.0320 0.0168 0.1091 0.0778 0.0213 0.0186 0.1378 0.0995 0.0316 0.0330 0.1337 0.0735 0.0319 0.0286 0.0498 0.0581 0.0224 0.0140 0.0741 0.0804 0.0155 0.0121 0.0866 0.1067 0.0266 0.0223 0.0901 0.0923 0.0272 0.0387 0.0465 0.0738 0.0220 0.0160 0.0554 0.0887 0.0243 0.0138 0.0790 0.1102 0.0300 0.0208 0.0844 0.1010 0.0192 0.0284 0.0751 0.0991 0.0331 0.0157 0.0674 0.1009 0.0272 0.0129 0.0758 0.1230 0.0319 0.0200 0.0984 0.0981 0.0298 0.0292 0.1095 0.1833 0.0422 0.0237 0.0964 0.1581 0.0389 0.0262 0.0655 0.1879 0.0427 0.0431 0.0990 0.1795 0.0268 0.0214 0.0742 0.1377 0.0367 0.0285 0.0920 0.1311 0.0331 0.0652 0.0779 0.1649 0.0540 0.0436 0.0942 0.2015 0.0280 0.0183 0.0591 0.0683 0.0410 0.0179 0.0786 0.0997 0.0360 0.0795 0.0979 0.1277 0.0751 0.0371 0.0873 0.1036 0.0225 0.0249 0.0747 0.0662 0.0347 0.0187 0.1072 0.0770 0.0329 0.0371 0.1675 0.1117 0.0458 0.0358 0.1450 0.0830 0.0390 0.0351 0.0691 0.0595 0.0443 0.0244 0.1247 0.1096 0.0327 0.0432 0.1075 0.1145 0.0595 0.0519 0.1609 0.0961 0.0398 0.0454 0.1075 0.0828 0.0439 0.0282 0.1060 0.0984 0.0371 0.0233 0.0935 0.1630 0.0466 0.0417 0.0802 0.1021 0.0541 0.0420 0.1809 0.1346 0.0759 0.0564 0.1908 0.1325 0.0362 0.0704 0.1278 0.1838 0.0833 0.0917 0.0859 0.2116 0.0401 0.0352 0.0852 0.0706 0.0594 0.0450 0.1540 0.1143 0.0518 0.1173 0.1497 0.1642 0.1014 0.0866 0.1340 0.1704 2 | -------------------------------------------------------------------------------- /test/data/scene.ops_8_8_8.result: -------------------------------------------------------------------------------- 1 | 0.0181 0.0186 0.0561 0.0348 0.0178 0.0088 0.0704 0.0495 0.0129 0.0130 0.0675 0.0456 0.0290 0.0247 0.0691 0.0404 0.0191 0.0207 0.0432 0.0348 0.0131 0.0073 0.0532 0.0490 0.0126 0.0121 0.0538 0.0395 0.0228 0.0174 0.0495 0.0393 0.0168 0.0236 0.0382 0.0391 0.0155 0.0100 0.0389 0.0586 0.0139 0.0135 0.0407 0.0462 0.0206 0.0153 0.0398 0.0465 0.0164 0.0212 0.0450 0.0521 0.0212 0.0121 0.0467 0.0698 0.0191 0.0132 0.0420 0.0501 0.0255 0.0158 0.0467 0.0575 0.0188 0.0179 0.0656 0.0875 0.0277 0.0159 0.0593 0.0881 0.0281 0.0192 0.0423 0.0675 0.0339 0.0248 0.0519 0.0801 0.0198 0.0141 0.0461 0.0689 0.0238 0.0183 0.0444 0.0725 0.0277 0.0485 0.0534 0.0744 0.0477 0.0247 0.0432 0.0810 0.0188 0.0107 0.0413 0.0453 0.0213 0.0115 0.0363 0.0551 0.0275 0.0562 0.0662 0.0585 0.0619 0.0240 0.0507 0.0669 0.0156 0.0130 0.0538 0.0332 0.0203 0.0120 0.0547 0.0493 0.0201 0.0267 0.0783 0.0524 0.0358 0.0220 0.0759 0.0517 0.0282 0.0315 0.0581 0.0342 0.0322 0.0150 0.0751 0.0445 0.0205 0.0190 0.0953 0.0487 0.0327 0.0287 0.0776 0.0401 0.0321 0.0335 0.0371 0.0284 0.0215 0.0124 0.0479 0.0454 0.0151 0.0131 0.0581 0.0508 0.0259 0.0222 0.0622 0.0457 0.0250 0.0449 0.0366 0.0347 0.0212 0.0140 0.0408 0.0562 0.0193 0.0127 0.0520 0.0532 0.0321 0.0218 0.0449 0.0503 0.0174 0.0335 0.0627 0.0640 0.0327 0.0180 0.0576 0.0778 0.0257 0.0150 0.0429 0.0702 0.0311 0.0186 0.0453 0.0604 0.0284 0.0297 0.0928 0.1272 0.0367 0.0301 0.0912 0.1183 0.0321 0.0282 0.0457 0.0945 0.0404 0.0373 0.0471 0.1153 0.0239 0.0265 0.0544 0.0922 0.0353 0.0335 0.0770 0.1050 0.0288 0.0698 0.0584 0.0899 0.0612 0.0390 0.0433 0.1230 0.0245 0.0189 0.0431 0.0434 0.0375 0.0193 0.0545 0.0583 0.0360 0.0907 0.0749 0.0737 0.0851 0.0355 0.0538 0.0630 0.0219 0.0256 0.0534 0.0364 0.0343 0.0202 0.0696 0.0461 0.0315 0.0416 0.1118 0.0615 0.0511 0.0329 0.0894 0.0515 0.0342 0.0352 0.0388 0.0247 0.0330 0.0201 0.0884 0.0493 0.0193 0.0224 0.0534 0.0364 0.0382 0.0306 0.0838 0.0427 0.0393 0.0497 0.0459 0.0320 0.0296 0.0206 0.0625 0.0561 0.0142 0.0184 0.0606 0.0515 0.0285 0.0272 0.0597 0.0306 0.0314 0.0503 0.0521 0.0290 0.0242 0.0218 0.0531 0.0377 0.0258 0.0206 0.0463 0.0707 0.0380 0.0287 0.0535 0.0504 0.0226 0.0422 0.0814 0.0703 0.0485 0.0347 0.0605 0.0485 0.0326 0.0175 0.0427 0.0849 0.0409 0.0300 0.0407 0.0493 0.0609 0.0406 0.1564 0.1393 0.0620 0.0684 0.1581 0.0951 0.0271 0.0390 0.0586 0.0708 0.0526 0.0694 0.0613 0.1256 0.0375 0.0347 0.0802 0.0866 0.0462 0.0605 0.1386 0.1041 0.0311 0.0968 0.0937 0.1006 0.0909 0.0617 0.0556 0.1387 0.0307 0.0290 0.0346 0.0514 0.0449 0.0290 0.0646 0.0660 0.0514 0.1366 0.0930 0.0964 0.1146 0.0570 0.0558 0.0682 0.0270 0.0462 0.0392 0.0288 0.0452 0.0278 0.0718 0.0257 0.0302 0.0546 0.0659 0.0621 0.0695 0.0517 0.0929 0.0505 0.0175 0.0185 0.0616 0.0447 0.0180 0.0093 0.0831 0.0660 0.0137 0.0132 0.0763 0.0545 0.0283 0.0235 0.0806 0.0486 0.0191 0.0200 0.0483 0.0430 0.0136 0.0077 0.0631 0.0653 0.0131 0.0119 0.0603 0.0477 0.0230 0.0173 0.0582 0.0465 0.0176 0.0221 0.0429 0.0501 0.0162 0.0102 0.0460 0.0770 0.0149 0.0135 0.0457 0.0563 0.0208 0.0156 0.0492 0.0562 0.0167 0.0208 0.0490 0.0656 0.0220 0.0112 0.0533 0.0890 0.0203 0.0135 0.0472 0.0596 0.0260 0.0160 0.0578 0.0695 0.0194 0.0183 0.0693 0.1093 0.0296 0.0143 0.0641 0.1086 0.0307 0.0188 0.0481 0.0800 0.0339 0.0255 0.0637 0.0931 0.0215 0.0131 0.0500 0.0858 0.0243 0.0178 0.0491 0.0903 0.0292 0.0475 0.0596 0.0887 0.0485 0.0251 0.0523 0.0953 0.0196 0.0099 0.0444 0.0573 0.0223 0.0114 0.0422 0.0726 0.0285 0.0552 0.0712 0.0717 0.0627 0.0240 0.0606 0.0808 0.0160 0.0131 0.0590 0.0422 0.0210 0.0118 0.0653 0.0642 0.0207 0.0265 0.0848 0.0632 0.0353 0.0222 0.0885 0.0626 0.0255 0.0298 0.0641 0.0422 0.0307 0.0144 0.0853 0.0571 0.0216 0.0195 0.1043 0.0600 0.0314 0.0297 0.0914 0.0468 0.0308 0.0295 0.0396 0.0342 0.0205 0.0113 0.0540 0.0588 0.0148 0.0119 0.0675 0.0635 0.0236 0.0224 0.0700 0.0509 0.0247 0.0380 0.0399 0.0404 0.0198 0.0128 0.0459 0.0702 0.0194 0.0121 0.0599 0.0609 0.0289 0.0215 0.0546 0.0574 0.0169 0.0302 0.0670 0.0725 0.0319 0.0153 0.0603 0.0866 0.0255 0.0147 0.0483 0.0770 0.0291 0.0195 0.0564 0.0697 0.0282 0.0300 0.0956 0.1482 0.0388 0.0248 0.0899 0.1340 0.0339 0.0278 0.0500 0.1071 0.0390 0.0393 0.0586 0.1257 0.0251 0.0235 0.0588 0.1057 0.0340 0.0305 0.0759 0.1126 0.0296 0.0669 0.0645 0.0970 0.0560 0.0391 0.0485 0.1328 0.0237 0.0170 0.0463 0.0502 0.0390 0.0183 0.0596 0.0728 0.0357 0.0850 0.0823 0.0808 0.0803 0.0339 0.0613 0.0741 0.0206 0.0245 0.0587 0.0429 0.0336 0.0181 0.0811 0.0594 0.0315 0.0393 0.1206 0.0718 0.0472 0.0318 0.1026 0.0597 0.0269 0.0267 0.0406 0.0305 0.0308 0.0188 0.0952 0.0613 0.0193 0.0211 0.0553 0.0379 0.0351 0.0351 0.0949 0.0448 0.0361 0.0380 0.0459 0.0413 0.0280 0.0154 0.0663 0.0680 0.0147 0.0173 0.0622 0.0542 0.0271 0.0287 0.0653 0.0361 0.0303 0.0401 0.0528 0.0323 0.0210 0.0170 0.0573 0.0399 0.0237 0.0193 0.0522 0.0713 0.0347 0.0289 0.0589 0.0428 0.0221 0.0367 0.0843 0.0761 0.0450 0.0253 0.0606 0.0495 0.0275 0.0160 0.0492 0.0860 0.0371 0.0318 0.0454 0.0530 0.0581 0.0386 0.1568 0.1475 0.0607 0.0527 0.1501 0.0993 0.0230 0.0370 0.0568 0.0701 0.0480 0.0681 0.0636 0.1265 0.0342 0.0271 0.0839 0.0861 0.0417 0.0491 0.1320 0.1093 0.0270 0.0883 0.0963 0.0888 0.0796 0.0619 0.0578 0.1323 0.0284 0.0252 0.0375 0.0501 0.0417 0.0276 0.0686 0.0738 0.0477 0.1213 0.1001 0.0906 0.1013 0.0546 0.0591 0.0709 0.0249 0.0408 0.0401 0.0324 0.0424 0.0275 0.0818 0.0305 0.0289 0.0477 0.0726 0.0580 0.0620 0.0486 0.0954 0.0502 0.0189 0.0179 0.0848 0.0733 0.0198 0.0104 0.1112 0.0981 0.0150 0.0131 0.1118 0.1126 0.0302 0.0253 0.1163 0.0780 0.0206 0.0203 0.0646 0.0696 0.0156 0.0090 0.0871 0.0969 0.0150 0.0122 0.0882 0.0931 0.0259 0.0173 0.0852 0.0800 0.0199 0.0234 0.0582 0.0837 0.0182 0.0118 0.0611 0.1118 0.0172 0.0141 0.0675 0.1112 0.0246 0.0152 0.0805 0.1018 0.0194 0.0215 0.0615 0.1036 0.0235 0.0121 0.0665 0.1227 0.0233 0.0133 0.0728 0.1169 0.0299 0.0162 0.0968 0.1222 0.0217 0.0194 0.0840 0.1734 0.0326 0.0151 0.0746 0.1495 0.0351 0.0190 0.0728 0.1494 0.0381 0.0274 0.1044 0.1538 0.0241 0.0141 0.0650 0.1342 0.0262 0.0176 0.0614 0.1243 0.0319 0.0486 0.0868 0.1612 0.0515 0.0262 0.0911 0.1601 0.0237 0.0110 0.0590 0.0934 0.0245 0.0117 0.0571 0.1049 0.0309 0.0554 0.1068 0.1323 0.0639 0.0247 0.0970 0.1379 0.0186 0.0133 0.0788 0.0709 0.0229 0.0126 0.0860 0.0939 0.0232 0.0262 0.1251 0.1221 0.0365 0.0234 0.1325 0.1049 0.0262 0.0280 0.0806 0.0649 0.0320 0.0168 0.1091 0.0778 0.0213 0.0186 0.1378 0.0995 0.0316 0.0330 0.1337 0.0735 0.0319 0.0286 0.0498 0.0581 0.0224 0.0140 0.0741 0.0804 0.0155 0.0121 0.0866 0.1067 0.0266 0.0223 0.0901 0.0923 0.0272 0.0387 0.0465 0.0738 0.0220 0.0160 0.0554 0.0887 0.0243 0.0138 0.0790 0.1102 0.0300 0.0208 0.0844 0.1010 0.0192 0.0284 0.0751 0.0991 0.0331 0.0157 0.0674 0.1009 0.0272 0.0129 0.0758 0.1230 0.0319 0.0200 0.0984 0.0981 0.0298 0.0292 0.1095 0.1833 0.0422 0.0237 0.0964 0.1581 0.0389 0.0262 0.0655 0.1879 0.0427 0.0431 0.0990 0.1795 0.0268 0.0214 0.0742 0.1377 0.0367 0.0285 0.0920 0.1311 0.0331 0.0652 0.0779 0.1649 0.0540 0.0436 0.0942 0.2015 0.0280 0.0183 0.0591 0.0683 0.0410 0.0179 0.0786 0.0997 0.0360 0.0795 0.0979 0.1277 0.0751 0.0371 0.0873 0.1036 0.0225 0.0249 0.0747 0.0662 0.0347 0.0187 0.1072 0.0770 0.0329 0.0371 0.1675 0.1117 0.0458 0.0358 0.1450 0.0830 0.0285 0.0244 0.0488 0.0392 0.0309 0.0183 0.1117 0.0847 0.0210 0.0184 0.0720 0.0701 0.0341 0.0381 0.1346 0.0750 0.0298 0.0315 0.0505 0.0422 0.0303 0.0139 0.0916 0.0807 0.0190 0.0165 0.0667 0.0778 0.0259 0.0271 0.0607 0.0590 0.0301 0.0347 0.0677 0.0563 0.0242 0.0165 0.0735 0.0609 0.0299 0.0195 0.0618 0.1160 0.0364 0.0241 0.0572 0.0775 0.0242 0.0299 0.0883 0.0786 0.0437 0.0218 0.0636 0.0648 0.0295 0.0154 0.0676 0.1493 0.0360 0.0333 0.0513 0.0611 0.0529 0.0360 0.1616 0.1264 0.0619 0.0437 0.1581 0.1041 0.0281 0.0332 0.0828 0.1358 0.0517 0.0726 0.0668 0.1595 0.0296 0.0254 0.0912 0.0555 0.0398 0.0396 0.1519 0.1064 0.0294 0.0778 0.1188 0.1498 0.0703 0.0662 0.0652 0.1852 0.0308 0.0245 0.0338 0.0481 0.0411 0.0245 0.0852 0.0794 0.0471 0.1012 0.1080 0.1100 0.0800 0.0596 0.0845 0.0847 0.0265 0.0377 0.0444 0.0433 0.0406 0.0251 0.0939 0.0448 0.0250 0.0405 0.0908 0.0830 0.0583 0.0550 0.1289 0.0724 2 | --------------------------------------------------------------------------------