├── .gitignore ├── README.md ├── ev-YOLOv6 ├── .gitignore ├── configs │ ├── gen1_optimized.py │ ├── gen1_optimized2.py │ ├── gen1_optimized_augment.py │ ├── gen1_optimized_augment2.py │ └── swinv2_yolov6l6_finetune.py ├── data │ ├── gen1.yaml │ └── gen4.yaml ├── requirements.txt ├── tools │ ├── eval.py │ └── train.py └── yolov6 │ ├── __init__.py │ ├── assigners │ ├── __init__.py │ ├── anchor_generator.py │ ├── assigner_utils.py │ ├── atss_assigner.py │ ├── iou2d_calculator.py │ └── tal_assigner.py │ ├── core │ ├── engine.py │ ├── evaler.py │ └── inferer.py │ ├── data │ ├── data_augment.py │ ├── data_load.py │ ├── datasets.py │ ├── gen1_2yolo.py │ └── gen4 │ │ ├── __init__.py │ │ ├── data_loader.py │ │ ├── data_sampler.py │ │ ├── dataset.py │ │ ├── gen4_2yolo.py │ │ ├── gen4_2yolo_raw.py │ │ ├── precompute_reps.py │ │ ├── test_event_files.npy │ │ ├── test_label_files.npy │ │ ├── train_event_files.npy │ │ ├── train_label_files.npy │ │ ├── val_event_files.npy │ │ └── val_label_files.npy │ ├── layers │ ├── common.py │ └── dbb_transforms.py │ ├── models │ ├── efficientrep.py │ ├── effidehead.py │ ├── end2end.py │ ├── heads │ │ ├── effidehead_distill_ns.py │ │ └── effidehead_fuseab.py │ ├── learned_repr.py │ ├── losses │ │ ├── loss.py │ │ ├── loss_distill.py │ │ ├── loss_distill_ns.py │ │ └── loss_fuseab.py │ ├── reppan.py │ ├── resnet50.py │ ├── swin_transformer_v2.py │ └── yolo.py │ ├── solver │ └── build.py │ ├── utils │ ├── Arial.ttf │ ├── RepOptimizer.py │ ├── checkpoint.py │ ├── config.py │ ├── ema.py │ ├── envs.py │ ├── events.py │ ├── figure_iou.py │ ├── general.py │ ├── metrics.py │ ├── nms.py │ └── torch_utils.py │ └── vis_utils.py ├── ev-licious ├── .gitignore ├── README.md ├── environment.yml ├── scripts │ ├── conversion │ │ ├── convert_h5_to_standard_format.py │ │ └── convert_to_standard_format.py │ ├── processing │ │ ├── convert_to_video.py │ │ ├── cut_events_by_time.py │ │ ├── filter_events.py │ │ ├── resize_events.py │ │ ├── write_events_to_rosbag.py │ │ └── write_images_to_rosbag.py │ └── visualization │ │ ├── 2d_coordinate_slice_events.py │ │ ├── 3d_animation_events_graph.py │ │ ├── 3d_animation_voxel_grid.py │ │ ├── 3d_visualization_events.py │ │ ├── event_rate_visualialization.py │ │ ├── events_to_rendering.py │ │ ├── half_half_rendering_events.py │ │ └── interactive_viz_events.py ├── setup.py ├── src │ └── evlicious │ │ ├── __init__.py │ │ ├── args.py │ │ ├── art │ │ ├── __init__.py │ │ ├── o3d_vis.py │ │ └── utils.py │ │ ├── io │ │ ├── __init__.py │ │ ├── bin_event_handle.py │ │ ├── dat_event_handle.py │ │ ├── h5_event_handle.py │ │ ├── npy_event_handle.py │ │ ├── npz_event_handle.py │ │ ├── rosbag_event_handle.py │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── dvs_msgs │ │ │ ├── _Event.py │ │ │ └── _EventArray.py │ │ │ ├── event_handle.py │ │ │ ├── events.py │ │ │ ├── fake_events.py │ │ │ ├── h5_writer.py │ │ │ ├── load_data.py │ │ │ ├── prophesee_utils.py │ │ │ ├── render.py │ │ │ ├── rosbag.py │ │ │ └── visualization.py │ │ └── tools │ │ ├── __init__.py │ │ ├── filters.py │ │ ├── task_manager.py │ │ └── utils.py └── tests │ └── data │ ├── events.h5 │ └── images │ ├── 000300.jpg │ ├── 000302.jpg │ ├── 000304.jpg │ ├── 000306.jpg │ ├── 000308.jpg │ ├── 000310.jpg │ ├── 000312.jpg │ ├── 000314.jpg │ ├── 000316.jpg │ ├── 000318.jpg │ ├── 000320.jpg │ ├── 000322.jpg │ ├── 000324.jpg │ ├── 000326.jpg │ ├── 000328.jpg │ ├── 000330.jpg │ ├── 000332.jpg │ ├── 000334.jpg │ ├── 000336.jpg │ ├── 000338.jpg │ ├── 000340.jpg │ ├── 000342.jpg │ ├── 000344.jpg │ ├── 000346.jpg │ ├── 000348.jpg │ ├── 000350.jpg │ ├── 000352.jpg │ ├── 000354.jpg │ ├── 000356.jpg │ ├── 000358.jpg │ ├── 000360.jpg │ ├── 000362.jpg │ ├── 000364.jpg │ ├── 000366.jpg │ ├── 000368.jpg │ ├── 000370.jpg │ ├── 000372.jpg │ ├── 000374.jpg │ ├── 000376.jpg │ ├── 000378.jpg │ ├── 000380.jpg │ ├── 000382.jpg │ ├── 000384.jpg │ ├── 000386.jpg │ ├── 000388.jpg │ ├── 000390.jpg │ ├── 000392.jpg │ ├── 000394.jpg │ ├── 000396.jpg │ ├── 000398.jpg │ ├── 000400.jpg │ ├── 000402.jpg │ ├── 000404.jpg │ ├── 000406.jpg │ ├── 000408.jpg │ ├── 000410.jpg │ ├── 000412.jpg │ ├── 000414.jpg │ ├── 000416.jpg │ ├── 000418.jpg │ ├── 000420.jpg │ ├── 000422.jpg │ ├── 000424.jpg │ ├── 000426.jpg │ ├── 000428.jpg │ ├── 000430.jpg │ ├── 000432.jpg │ ├── 000434.jpg │ ├── 000436.jpg │ ├── 000438.jpg │ ├── 000440.jpg │ ├── 000442.jpg │ ├── 000444.jpg │ ├── 000446.jpg │ ├── 000448.jpg │ ├── 000450.jpg │ ├── 000452.jpg │ ├── 000454.jpg │ ├── 000456.jpg │ ├── 000458.jpg │ ├── 000460.jpg │ ├── 000462.jpg │ ├── 000464.jpg │ ├── 000466.jpg │ ├── 000468.jpg │ ├── 000470.jpg │ ├── 000472.jpg │ ├── 000474.jpg │ ├── 000476.jpg │ ├── 000478.jpg │ ├── 000480.jpg │ ├── 000482.jpg │ ├── 000484.jpg │ ├── 000486.jpg │ ├── 000488.jpg │ ├── 000490.jpg │ ├── 000492.jpg │ ├── 000494.jpg │ ├── 000496.jpg │ ├── 000498.jpg │ └── timestamps.txt ├── gryffin ├── .codecov.yml ├── .github │ └── workflows │ │ ├── continuous-integration.yml │ │ └── python-publish.yml ├── .gitignore ├── .readthedocs.yaml ├── INSTALL.md ├── LICENSE.md ├── MANIFEST.in ├── README.md ├── config.json ├── docs │ ├── Makefile │ ├── README.rst │ ├── make.bat │ ├── requirements.txt │ └── source │ │ ├── _static │ │ └── custom.css │ │ ├── api_documentation.rst │ │ ├── citation.rst │ │ ├── cli_documentation.rst │ │ ├── conf.py │ │ ├── configuration.rst │ │ ├── getting_started.rst │ │ ├── index.rst │ │ ├── tutorial.rst │ │ └── tutorials │ │ ├── advanced_usage.ipynb │ │ ├── assets │ │ ├── advanced_usage.gif │ │ ├── hoip_optimizer_performance.png │ │ └── hoip_space.png │ │ ├── basic_usage.ipynb │ │ ├── perovskites.ipynb │ │ ├── perovskites.pkl │ │ ├── robot.rst │ │ └── tf_params.pickle ├── pyproject.toml ├── setup.cfg ├── setup.py ├── src │ └── gryffin │ │ ├── __init__.py │ │ ├── _version.py │ │ ├── acquisition │ │ ├── __init__.py │ │ ├── acquisition.py │ │ ├── genetic_optimizer │ │ │ ├── __init__.py │ │ │ └── genetic_optimizer.py │ │ └── gradient_optimizer │ │ │ ├── __init__.py │ │ │ ├── adam_optimizer.py │ │ │ ├── gradient_optimizer.py │ │ │ ├── naive_categorical_optimizer.py │ │ │ └── naive_discrete_optimizer.py │ │ ├── bayesian_network │ │ ├── __init__.py │ │ ├── bayesian_network.py │ │ ├── category_reshaper.py │ │ ├── kernel_evaluations.c │ │ ├── kernel_evaluations.html │ │ ├── kernel_evaluations.pyx │ │ ├── kernel_evaluations.pyxbld │ │ ├── kernel_evaluations.pyxbldc │ │ ├── kernel_prob_reshaping.c │ │ ├── kernel_prob_reshaping.pyx │ │ ├── kernel_prob_reshaping.pyxbld │ │ ├── kernel_prob_reshaping.pyxbldc │ │ └── torch_interface │ │ │ ├── __init__.py │ │ │ ├── bnn.py │ │ │ └── numpy_graph.py │ │ ├── benchmark_functions │ │ ├── __init__.py │ │ ├── benchmark_functions_cat.py │ │ └── benchmark_functions_cont.py │ │ ├── cli.py │ │ ├── database_handler │ │ ├── __init__.py │ │ ├── database_handler.py │ │ ├── db_cache.py │ │ ├── db_werkzeug.py │ │ ├── json_writers │ │ │ ├── __init__.py │ │ │ └── db_writer.py │ │ ├── pandas_writers │ │ │ ├── __init__.py │ │ │ └── db_writer.py │ │ ├── pickle_writers │ │ │ ├── __init__.py │ │ │ └── db_writer.py │ │ └── sqlite_interface │ │ │ ├── __init__.py │ │ │ ├── sqlite_database.py │ │ │ ├── sqlite_interface.py │ │ │ └── sqlite_operations.py │ │ ├── descriptor_generator │ │ ├── __init__.py │ │ ├── descriptor_generator.py │ │ └── generator.py │ │ ├── gryffin.py │ │ ├── observation_processor │ │ ├── __init__.py │ │ └── observation_processor.py │ │ ├── random_sampler │ │ ├── __init__.py │ │ └── random_sampler.py │ │ ├── sample_selector │ │ ├── __BACKUP_sample_selector.py │ │ ├── __init__.py │ │ └── sample_selector.py │ │ └── utilities │ │ ├── __init__.py │ │ ├── category_parser.py │ │ ├── config_parser.py │ │ ├── constraint_utils.py │ │ ├── decorators.py │ │ ├── defaults.py │ │ ├── exceptions.py │ │ ├── infos.py │ │ ├── json_parser.py │ │ ├── logger.py │ │ ├── params.pkl │ │ └── pickle_parser.py ├── tests │ ├── test_categorical.py │ ├── test_constraints.py │ ├── test_continuous.py │ ├── test_gryffin.py │ └── test_mixed.py ├── tox.ini └── versioneer.py ├── n_imagenet ├── .gitignore ├── base │ ├── __init__.py │ ├── data │ │ ├── data_container.py │ │ └── dataset.py │ ├── models │ │ └── model_container.py │ ├── train │ │ ├── caption_trainer.py │ │ ├── common_trainer.py │ │ ├── metrics.py │ │ ├── mini_batch_trainer.py │ │ └── trainer.py │ └── utils │ │ ├── parse_utils.py │ │ ├── time_utils.py │ │ └── tracker.py ├── environment.yml ├── real_cnn_model │ ├── .gitignore │ ├── __init__.py │ ├── configs │ │ └── imagenet │ │ │ ├── cnn_adam_acc_four_channel_big_kernel_random_idx.ini │ │ │ ├── cnn_adam_acc_four_channel_big_kernel_random_idx_mini.ini │ │ │ ├── cnn_adam_acc_one_channel_big_kernel_random_idx.ini │ │ │ ├── cnn_adam_acc_one_channel_big_kernel_random_idx_mini.ini │ │ │ ├── cnn_adam_acc_sort_big_kernel_random_idx.ini │ │ │ ├── cnn_adam_acc_two_channel_big_kernel_random_idx.ini │ │ │ ├── cnn_adam_acc_two_channel_big_kernel_random_idx_mini.ini │ │ │ └── cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini │ ├── data │ │ ├── .gitignore │ │ ├── data_container.py │ │ └── imagenet.py │ ├── main.py │ ├── models │ │ └── model_container.py │ └── train │ │ └── trainer.py └── scripts │ ├── mininimagenet_event_histogram.bash │ ├── mininimagenet_event_histogram.job │ ├── mininimagenet_event_stack.bash │ ├── mininimagenet_event_stack.job │ ├── mininimagenet_optimized.bash │ ├── mininimagenet_optimized.job │ ├── mininimagenet_time_surface.bash │ ├── mininimagenet_time_surface.job │ ├── mininimagenet_tore.bash │ ├── mininimagenet_tore.job │ ├── mininimagenet_voxel_grid.bash │ └── mininimagenet_voxel_grid.job ├── representations ├── event_stack.py ├── gen1_transforms.py ├── gen4_transforms.py ├── optimized_representation.py ├── representation_search │ ├── __init__.py │ ├── chosen_indexes.py │ ├── compute_otmi.py │ ├── gen1_compute.py │ ├── gromov_wasserstein.py │ ├── mixed_density_event_stack.py │ ├── operations.py │ └── optimization.py ├── time_surface.py └── tore.py └── viz ├── 1_optimization_details.py ├── 2_map_gwd_correlation.py ├── 3_samples_view.py ├── 4_toy_examples.py ├── 5_appendix_plots.py └── ergo12_visualization.png /ev-YOLOv6/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | **/*.pyc 6 | 7 | # C extensions 8 | 9 | # Distribution / packaging 10 | 11 | .Python 12 | videos/ 13 | build/ 14 | runs/ 15 | weights/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | db.sqlite3 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # pyenv 78 | .python-version 79 | 80 | # celery beat schedule file 81 | celerybeat-schedule 82 | 83 | # SageMath parsed files 84 | *.sage.py 85 | 86 | # Environments 87 | .env 88 | .venv 89 | env/ 90 | venv/ 91 | ENV/ 92 | env.bak/ 93 | venv.bak/ 94 | 95 | # Spyder project settings 96 | .spyderproject 97 | .spyproject 98 | 99 | # Rope project settings 100 | .ropeproject 101 | 102 | # custom 103 | .DS_Store 104 | 105 | # Pytorch 106 | *.pth 107 | 108 | #vscode 109 | .vscode/* 110 | 111 | #user scripts 112 | *.sh 113 | 114 | # model files 115 | *.onnx 116 | *.pt 117 | *.engine 118 | -------------------------------------------------------------------------------- /ev-YOLOv6/configs/gen1_optimized.py: -------------------------------------------------------------------------------- 1 | # YOLOv6l6 model 2 | model = dict( 3 | type="YOLOv6l6", 4 | pretrained="/shares/rpg.ifi.uzh/nzubic/event_representation_study/GEN1/gen1_optimized/weights/best_ckpt.pt", 5 | depth_multiple=1.0, 6 | width_multiple=1.0, 7 | backbone=dict( 8 | type="SwinTransformerV2", 9 | num_repeats=[1, 6, 12, 18, 6, 6], 10 | out_channels=[64, 128, 256, 512, 768, 1024], 11 | csp_e=float(1) / 2, 12 | fuse_P2=True, 13 | ), 14 | neck=dict( 15 | type="CSPRepBiFPANNeck_P6", 16 | num_repeats=[12, 12, 12, 12, 12, 12], 17 | out_channels=[512, 256, 128, 256, 512, 1024], 18 | csp_e=float(1) / 2, 19 | ), 20 | head=dict( 21 | type="EffiDeHead", 22 | in_channels=[128, 256, 512, 1024], 23 | num_layers=4, 24 | anchors=1, 25 | strides=[8, 16, 32, 64], 26 | atss_warmup_epoch=4, 27 | iou_type="giou", 28 | use_dfl=True, 29 | reg_max=16, # if use_dfl is False, please set reg_max to 0 30 | distill_weight={ 31 | "class": 1.0, 32 | "dfl": 1.0, 33 | }, 34 | ), 35 | ) 36 | 37 | solver = dict( 38 | optim="SGD", 39 | lr_scheduler="Cosine", 40 | lr0=0.0032, 41 | lrf=0.12, 42 | momentum=0.843, 43 | weight_decay=0.00036, 44 | warmup_epochs=2.0, 45 | warmup_momentum=0.5, 46 | warmup_bias_lr=0.05, 47 | ) 48 | 49 | data_aug = dict( 50 | hsv_h=0.0138, 51 | hsv_s=0.664, 52 | hsv_v=0.464, 53 | degrees=0.373, 54 | translate=0.245, 55 | scale=0.898, 56 | shear=0.602, 57 | flipud=0.00856, 58 | fliplr=0.5, 59 | mosaic=1.0, 60 | mixup=0.243, 61 | ) 62 | training_mode = "conv_silu" 63 | -------------------------------------------------------------------------------- /ev-YOLOv6/configs/gen1_optimized2.py: -------------------------------------------------------------------------------- 1 | # YOLOv6l6 model 2 | model = dict( 3 | type="YOLOv6l6", 4 | pretrained="/shares/rpg.ifi.uzh/nzubic/event_representation_study/GEN1/gen1_optimized_2/weights/best_ckpt.pt", 5 | depth_multiple=1.0, 6 | width_multiple=1.0, 7 | backbone=dict( 8 | type="SwinTransformerV2", 9 | num_repeats=[1, 6, 12, 18, 6, 6], 10 | out_channels=[64, 128, 256, 512, 768, 1024], 11 | csp_e=float(1) / 2, 12 | fuse_P2=True, 13 | ), 14 | neck=dict( 15 | type="CSPRepBiFPANNeck_P6", 16 | num_repeats=[12, 12, 12, 12, 12, 12], 17 | out_channels=[512, 256, 128, 256, 512, 1024], 18 | csp_e=float(1) / 2, 19 | ), 20 | head=dict( 21 | type="EffiDeHead", 22 | in_channels=[128, 256, 512, 1024], 23 | num_layers=4, 24 | anchors=1, 25 | strides=[8, 16, 32, 64], 26 | atss_warmup_epoch=4, 27 | iou_type="giou", 28 | use_dfl=True, 29 | reg_max=16, # if use_dfl is False, please set reg_max to 0 30 | distill_weight={ 31 | "class": 1.0, 32 | "dfl": 1.0, 33 | }, 34 | ), 35 | ) 36 | 37 | solver = dict( 38 | optim="SGD", 39 | lr_scheduler="Cosine", 40 | lr0=0.0032, 41 | lrf=0.12, 42 | momentum=0.843, 43 | weight_decay=0.00036, 44 | warmup_epochs=2.0, 45 | warmup_momentum=0.5, 46 | warmup_bias_lr=0.05, 47 | ) 48 | 49 | data_aug = dict( 50 | hsv_h=0.0138, 51 | hsv_s=0.664, 52 | hsv_v=0.464, 53 | degrees=0.373, 54 | translate=0.245, 55 | scale=0.898, 56 | shear=0.602, 57 | flipud=0.00856, 58 | fliplr=0.5, 59 | mosaic=1.0, 60 | mixup=0.243, 61 | ) 62 | training_mode = "conv_silu" 63 | -------------------------------------------------------------------------------- /ev-YOLOv6/configs/gen1_optimized_augment.py: -------------------------------------------------------------------------------- 1 | # YOLOv6l6 model 2 | model = dict( 3 | type="YOLOv6l6", 4 | pretrained="/shares/rpg.ifi.uzh/nzubic/event_representation_study/GEN1/gen1_optimized_augment/weights/best_ckpt.pt", 5 | depth_multiple=1.0, 6 | width_multiple=1.0, 7 | backbone=dict( 8 | type="SwinTransformerV2", 9 | num_repeats=[1, 6, 12, 18, 6, 6], 10 | out_channels=[64, 128, 256, 512, 768, 1024], 11 | csp_e=float(1) / 2, 12 | fuse_P2=True, 13 | ), 14 | neck=dict( 15 | type="CSPRepBiFPANNeck_P6", 16 | num_repeats=[12, 12, 12, 12, 12, 12], 17 | out_channels=[512, 256, 128, 256, 512, 1024], 18 | csp_e=float(1) / 2, 19 | ), 20 | head=dict( 21 | type="EffiDeHead", 22 | in_channels=[128, 256, 512, 1024], 23 | num_layers=4, 24 | anchors=1, 25 | strides=[8, 16, 32, 64], 26 | atss_warmup_epoch=4, 27 | iou_type="giou", 28 | use_dfl=True, 29 | reg_max=16, # if use_dfl is False, please set reg_max to 0 30 | distill_weight={ 31 | "class": 1.0, 32 | "dfl": 1.0, 33 | }, 34 | ), 35 | ) 36 | 37 | solver = dict( 38 | optim="SGD", 39 | lr_scheduler="Cosine", 40 | lr0=0.0032, 41 | lrf=0.12, 42 | momentum=0.843, 43 | weight_decay=0.00036, 44 | warmup_epochs=2.0, 45 | warmup_momentum=0.5, 46 | warmup_bias_lr=0.05, 47 | ) 48 | 49 | data_aug = dict( 50 | hsv_h=0.0138, 51 | hsv_s=0.664, 52 | hsv_v=0.464, 53 | degrees=0.373, 54 | translate=0.245, 55 | scale=0.898, 56 | shear=0.602, 57 | flipud=0.00856, 58 | fliplr=0.5, 59 | mosaic=1.0, 60 | mixup=0.243, 61 | ) 62 | training_mode = "conv_silu" 63 | -------------------------------------------------------------------------------- /ev-YOLOv6/configs/gen1_optimized_augment2.py: -------------------------------------------------------------------------------- 1 | # YOLOv6l6 model 2 | model = dict( 3 | type="YOLOv6l6", 4 | pretrained="/shares/rpg.ifi.uzh/nzubic/event_representation_study/GEN1/gen1_optimized_augment_2/weights/best_ckpt.pt", 5 | depth_multiple=1.0, 6 | width_multiple=1.0, 7 | backbone=dict( 8 | type="SwinTransformerV2", 9 | num_repeats=[1, 6, 12, 18, 6, 6], 10 | out_channels=[64, 128, 256, 512, 768, 1024], 11 | csp_e=float(1) / 2, 12 | fuse_P2=True, 13 | ), 14 | neck=dict( 15 | type="CSPRepBiFPANNeck_P6", 16 | num_repeats=[12, 12, 12, 12, 12, 12], 17 | out_channels=[512, 256, 128, 256, 512, 1024], 18 | csp_e=float(1) / 2, 19 | ), 20 | head=dict( 21 | type="EffiDeHead", 22 | in_channels=[128, 256, 512, 1024], 23 | num_layers=4, 24 | anchors=1, 25 | strides=[8, 16, 32, 64], 26 | atss_warmup_epoch=4, 27 | iou_type="giou", 28 | use_dfl=True, 29 | reg_max=16, # if use_dfl is False, please set reg_max to 0 30 | distill_weight={ 31 | "class": 1.0, 32 | "dfl": 1.0, 33 | }, 34 | ), 35 | ) 36 | 37 | solver = dict( 38 | optim="SGD", 39 | lr_scheduler="Cosine", 40 | lr0=0.0032, 41 | lrf=0.12, 42 | momentum=0.843, 43 | weight_decay=0.00036, 44 | warmup_epochs=2.0, 45 | warmup_momentum=0.5, 46 | warmup_bias_lr=0.05, 47 | ) 48 | 49 | data_aug = dict( 50 | hsv_h=0.0138, 51 | hsv_s=0.664, 52 | hsv_v=0.464, 53 | degrees=0.373, 54 | translate=0.245, 55 | scale=0.898, 56 | shear=0.602, 57 | flipud=0.00856, 58 | fliplr=0.5, 59 | mosaic=1.0, 60 | mixup=0.243, 61 | ) 62 | training_mode = "conv_silu" 63 | -------------------------------------------------------------------------------- /ev-YOLOv6/configs/swinv2_yolov6l6_finetune.py: -------------------------------------------------------------------------------- 1 | # YOLOv6l6 model 2 | model = dict( 3 | type="YOLOv6l6", 4 | pretrained="/shares/rpg.ifi.uzh/nzubic/event_representation_study/swinv2_yolov6l6.pt", 5 | depth_multiple=1.0, 6 | width_multiple=1.0, 7 | backbone=dict( 8 | type="SwinTransformerV2", 9 | num_repeats=[1, 6, 12, 18, 6, 6], 10 | out_channels=[64, 128, 256, 512, 768, 1024], 11 | csp_e=float(1) / 2, 12 | fuse_P2=True, 13 | ), 14 | neck=dict( 15 | type="CSPRepBiFPANNeck_P6", 16 | num_repeats=[12, 12, 12, 12, 12, 12], 17 | out_channels=[512, 256, 128, 256, 512, 1024], 18 | csp_e=float(1) / 2, 19 | ), 20 | head=dict( 21 | type="EffiDeHead", 22 | in_channels=[128, 256, 512, 1024], 23 | num_layers=4, 24 | anchors=1, 25 | strides=[8, 16, 32, 64], 26 | atss_warmup_epoch=4, 27 | iou_type="giou", 28 | use_dfl=True, 29 | reg_max=16, # if use_dfl is False, please set reg_max to 0 30 | distill_weight={ 31 | "class": 1.0, 32 | "dfl": 1.0, 33 | }, 34 | ), 35 | ) 36 | 37 | solver = dict( 38 | optim="SGD", 39 | lr_scheduler="Cosine", 40 | lr0=0.0032, 41 | lrf=0.12, 42 | momentum=0.843, 43 | weight_decay=0.00036, 44 | warmup_epochs=2.0, 45 | warmup_momentum=0.5, 46 | warmup_bias_lr=0.05, 47 | ) 48 | 49 | data_aug = dict( 50 | hsv_h=0.0138, 51 | hsv_s=0.664, 52 | hsv_v=0.464, 53 | degrees=0.373, 54 | translate=0.245, 55 | scale=0.898, 56 | shear=0.602, 57 | flipud=0.00856, 58 | fliplr=0.5, 59 | mosaic=1.0, 60 | mixup=0.243, 61 | ) 62 | training_mode = "conv_silu" 63 | -------------------------------------------------------------------------------- /ev-YOLOv6/data/gen1.yaml: -------------------------------------------------------------------------------- 1 | train: "/shares/rpg.ifi.uzh/dgehrig/gen1/training.h5" # train 2 | val: "/shares/rpg.ifi.uzh/dgehrig/gen1/validation.h5" # val 3 | test: "/shares/rpg.ifi.uzh/dgehrig/gen1/testing.h5" # test (optional) 4 | anno_path: "/shares/rpg.ifi.uzh/nzubic/event_representation_study/GEN1_annotations/annotations/instances_valid.json" 5 | 6 | # whether it is coco dataset, only coco dataset should be set to True 7 | is_coco: False 8 | 9 | # Classes 10 | nc: 2 # number of classes 11 | names: ["car", "pedestrian"] # class names 12 | -------------------------------------------------------------------------------- /ev-YOLOv6/data/gen4.yaml: -------------------------------------------------------------------------------- 1 | train: "/shares/rpg.ifi.uzh/nzubic/datasets/gen4/OptimizedRepresentation/train" # train 2 | val: "/shares/rpg.ifi.uzh/nzubic/datasets/gen4/OptimizedRepresentation/val" # val 3 | test: "/shares/rpg.ifi.uzh/nzubic/datasets/gen4/OptimizedRepresentation/test" # test (optional) 4 | anno_path: "/shares/rpg.ifi.uzh/nzubic/event_representation_study/GEN4_annotations/annotations/instances_valid.json" 5 | 6 | # whether it is coco dataset, only coco dataset should be set to True. 7 | is_coco: False 8 | # Classes 9 | nc: 3 # number of classes 10 | names: ["pedestrian", "two wheeler", "car"] # class names 11 | -------------------------------------------------------------------------------- /ev-YOLOv6/requirements.txt: -------------------------------------------------------------------------------- 1 | # pip install -r requirements.txt 2 | # python3.8 environment 3 | 4 | #torch>=1.8.0 5 | #torchvision>=0.9.0 6 | numpy>=1.18.5 7 | opencv-python>=4.1.2 8 | PyYAML>=5.3.1 9 | scipy>=1.4.1 10 | tqdm>=4.41.0 11 | addict>=2.4.0 12 | tensorboard>=2.7.0 13 | pycocotools>=2.0 14 | onnx>=1.10.0 # ONNX export 15 | onnx-simplifier>=0.3.6 # ONNX simplifier 16 | thop # FLOPs computation 17 | #pytorch_quantization>=2.1.1 18 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/__init__.py -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/assigners/__init__.py: -------------------------------------------------------------------------------- 1 | from .atss_assigner import ATSSAssigner 2 | from .tal_assigner import TaskAlignedAssigner 3 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/__init__.py -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/data_loader.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | from torch.utils.data.dataloader import default_collate 4 | from data_sampler import RandomContinuousSampler 5 | 6 | 7 | class Loader: 8 | def __init__( 9 | self, 10 | dataset, 11 | mode, 12 | batch_size, 13 | num_workers, 14 | pin_memory, 15 | drop_last, 16 | sampler, 17 | data_index=None, 18 | ): 19 | if mode == "training": 20 | self.loader = torch.utils.data.DataLoader( 21 | dataset, 22 | batch_size=batch_size, 23 | sampler=sampler, 24 | num_workers=num_workers, 25 | pin_memory=pin_memory, 26 | drop_last=drop_last, 27 | collate_fn=collate_events, 28 | ) 29 | else: 30 | self.loader = torch.utils.data.DataLoader( 31 | dataset, 32 | batch_size=batch_size, 33 | num_workers=num_workers, 34 | pin_memory=pin_memory, 35 | drop_last=drop_last, 36 | collate_fn=collate_events_test, 37 | ) 38 | 39 | def __iter__(self): 40 | for data in self.loader: 41 | yield data 42 | 43 | def __len__(self): 44 | return len(self.loader) 45 | 46 | 47 | def collate_events(data): 48 | batch_labels = [] 49 | batch_pos_events = [] 50 | batch_neg_events = [] 51 | idx_batch = 0 52 | 53 | for d in data: # different batch 54 | for idx in range(len(d[0])): 55 | label = d[0][idx] 56 | lb = np.concatenate( 57 | [label, idx_batch * np.ones((len(label), 1), dtype=np.float32)], 1 58 | ) 59 | 60 | batch_labels.append(lb) 61 | idx_batch += 1 62 | batch_pos_events.append(d[1]) 63 | batch_neg_events.append(d[2]) 64 | labels = np.concatenate(batch_labels, 0) 65 | return labels, batch_pos_events, batch_neg_events 66 | 67 | 68 | def collate_events_test(data): 69 | labels = [] 70 | pos_events = [] 71 | neg_events = [] 72 | idx_batch = 0 73 | 74 | for d in data: 75 | for idx in range(len(d[0])): 76 | label = d[0][idx] 77 | lb = np.concatenate( 78 | [label, idx_batch * np.ones((len(label), 1), dtype=np.float32)], 1 79 | ) 80 | labels.append(lb) 81 | idx_batch += 1 82 | pos_events.append(d[1]) 83 | neg_events.append(d[2]) 84 | 85 | labels = np.concatenate(labels, 0) 86 | 87 | return labels, pos_events, neg_events 88 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/data_sampler.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import numba as nb 3 | from torch.utils.data.sampler import Sampler 4 | 5 | 6 | class RandomContinuousSampler(Sampler): 7 | r"""Samples elements randomly from a given list of indices, without replacement. 8 | Arguments: 9 | indices (sequence): a sequence of indices 10 | """ 11 | 12 | def __init__(self, data_len, num, data_index): 13 | self.dataset = data_len 14 | self.num = num 15 | self.data_index = data_index 16 | 17 | def __iter__(self): 18 | self.indices = random_batch_indice(self.dataset, self.num, self.data_index) 19 | return (self.indices[i] for i in range(len(self.indices))) 20 | 21 | def __len__(self): 22 | return len(self.indices) 23 | 24 | 25 | # get random continuous random numbers 26 | @nb.jit() 27 | def random_batch_indice(data_len, num, index_list): 28 | """ 29 | :param data_len: length of dataset 30 | :param num: continuous random numbers, e.g. num=2 31 | """ 32 | data_list = list(range(data_len)) 33 | split_list = [] 34 | for idx in range(data_len // num): 35 | batch = data_list[idx * num : (idx + 1) * num] 36 | split_list.append(batch) 37 | for i, value in enumerate(split_list): 38 | for j in range(len(value)): 39 | if value[j] in index_list: 40 | split_list.remove(value) 41 | continue 42 | split_list = np.array(split_list) 43 | np.random.shuffle(split_list) 44 | return split_list.reshape(-1) 45 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/test_event_files.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/test_event_files.npy -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/test_label_files.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/test_label_files.npy -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/train_event_files.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/train_event_files.npy -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/train_label_files.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/train_label_files.npy -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/val_event_files.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/val_event_files.npy -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/data/gen4/val_label_files.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/data/gen4/val_label_files.npy -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/layers/dbb_transforms.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | import torch.nn.functional as F 4 | 5 | 6 | def transI_fusebn(kernel, bn): 7 | gamma = bn.weight 8 | std = (bn.running_var + bn.eps).sqrt() 9 | return ( 10 | kernel * ((gamma / std).reshape(-1, 1, 1, 1)), 11 | bn.bias - bn.running_mean * gamma / std, 12 | ) 13 | 14 | 15 | def transII_addbranch(kernels, biases): 16 | return sum(kernels), sum(biases) 17 | 18 | 19 | def transIII_1x1_kxk(k1, b1, k2, b2, groups): 20 | if groups == 1: 21 | k = F.conv2d(k2, k1.permute(1, 0, 2, 3)) # 22 | b_hat = (k2 * b1.reshape(1, -1, 1, 1)).sum((1, 2, 3)) 23 | else: 24 | k_slices = [] 25 | b_slices = [] 26 | k1_T = k1.permute(1, 0, 2, 3) 27 | k1_group_width = k1.size(0) // groups 28 | k2_group_width = k2.size(0) // groups 29 | for g in range(groups): 30 | k1_T_slice = k1_T[:, g * k1_group_width : (g + 1) * k1_group_width, :, :] 31 | k2_slice = k2[g * k2_group_width : (g + 1) * k2_group_width, :, :, :] 32 | k_slices.append(F.conv2d(k2_slice, k1_T_slice)) 33 | b_slices.append( 34 | ( 35 | k2_slice 36 | * b1[g * k1_group_width : (g + 1) * k1_group_width].reshape( 37 | 1, -1, 1, 1 38 | ) 39 | ).sum((1, 2, 3)) 40 | ) 41 | k, b_hat = transIV_depthconcat(k_slices, b_slices) 42 | return k, b_hat + b2 43 | 44 | 45 | def transIV_depthconcat(kernels, biases): 46 | return torch.cat(kernels, dim=0), torch.cat(biases) 47 | 48 | 49 | def transV_avg(channels, kernel_size, groups): 50 | input_dim = channels // groups 51 | k = torch.zeros((channels, input_dim, kernel_size, kernel_size)) 52 | k[np.arange(channels), np.tile(np.arange(input_dim), groups), :, :] = ( 53 | 1.0 / kernel_size**2 54 | ) 55 | return k 56 | 57 | 58 | # This has not been tested with non-square kernels (kernel.size(2) != kernel.size(3)) nor even-size kernels 59 | def transVI_multiscale(kernel, target_kernel_size): 60 | H_pixels_to_pad = (target_kernel_size - kernel.size(2)) // 2 61 | W_pixels_to_pad = (target_kernel_size - kernel.size(3)) // 2 62 | return F.pad( 63 | kernel, [H_pixels_to_pad, H_pixels_to_pad, W_pixels_to_pad, W_pixels_to_pad] 64 | ) 65 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/solver/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding:utf-8 -*- 3 | import os 4 | import math 5 | 6 | import torch 7 | import torch.nn as nn 8 | 9 | from yolov6.utils.events import LOGGER 10 | 11 | 12 | def build_optimizer(cfg, model): 13 | """Build optimizer from cfg file.""" 14 | g_bnw, g_w, g_b = [], [], [] 15 | for v in model.modules(): 16 | if hasattr(v, "bias") and isinstance(v.bias, nn.Parameter): 17 | g_b.append(v.bias) 18 | if isinstance(v, nn.BatchNorm2d): 19 | g_bnw.append(v.weight) 20 | elif hasattr(v, "weight") and isinstance(v.weight, nn.Parameter): 21 | g_w.append(v.weight) 22 | 23 | assert ( 24 | cfg.solver.optim == "SGD" or "Adam" 25 | ), "ERROR: unknown optimizer, use SGD defaulted" 26 | if cfg.solver.optim == "SGD": 27 | optimizer = torch.optim.SGD( 28 | g_bnw, lr=cfg.solver.lr0, momentum=cfg.solver.momentum, nesterov=True 29 | ) 30 | elif cfg.solver.optim == "Adam": 31 | optimizer = torch.optim.Adam( 32 | g_bnw, lr=cfg.solver.lr0, betas=(cfg.solver.momentum, 0.999) 33 | ) 34 | 35 | optimizer.add_param_group({"params": g_w, "weight_decay": cfg.solver.weight_decay}) 36 | optimizer.add_param_group({"params": g_b}) 37 | 38 | del g_bnw, g_w, g_b 39 | return optimizer 40 | 41 | 42 | def build_lr_scheduler(cfg, optimizer, epochs): 43 | """Build learning rate scheduler from cfg file.""" 44 | if cfg.solver.lr_scheduler == "Cosine": 45 | lf = ( 46 | lambda x: ((1 - math.cos(x * math.pi / epochs)) / 2) * (cfg.solver.lrf - 1) 47 | + 1 48 | ) 49 | elif cfg.solver.lr_scheduler == "Constant": 50 | lf = lambda x: 1.0 51 | else: 52 | LOGGER.error("unknown lr scheduler, use Cosine defaulted") 53 | 54 | scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lf) 55 | return scheduler, lf 56 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/utils/Arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-YOLOv6/yolov6/utils/Arial.ttf -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/utils/checkpoint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding:utf-8 -*- 3 | import os 4 | import shutil 5 | import torch 6 | import os.path as osp 7 | from yolov6.utils.events import LOGGER 8 | from yolov6.utils.torch_utils import fuse_model 9 | 10 | 11 | def load_state_dict(weights, model, map_location=None): 12 | """Load weights from checkpoint file, only assign weights those layers' name and shape are match.""" 13 | ckpt = torch.load(weights, map_location=map_location) 14 | state_dict = ckpt["model"].float().state_dict() 15 | model_state_dict = model.state_dict() 16 | state_dict = { 17 | k: v 18 | for k, v in state_dict.items() 19 | if k in model_state_dict and v.shape == model_state_dict[k].shape 20 | } 21 | model.load_state_dict(state_dict, strict=False) 22 | del ckpt, state_dict, model_state_dict 23 | return model 24 | 25 | 26 | def load_checkpoint(weights, map_location=None, inplace=True, fuse=True): 27 | """Load model from checkpoint file.""" 28 | LOGGER.info("Loading checkpoint from {}".format(weights)) 29 | ckpt = torch.load(weights, map_location=map_location) # load 30 | model = ckpt["ema" if ckpt.get("ema") else "model"].float() 31 | if fuse: 32 | LOGGER.info("\nFusing model...") 33 | model = fuse_model(model).eval() 34 | else: 35 | model = model.eval() 36 | return model 37 | 38 | 39 | def save_checkpoint(ckpt, is_best, save_dir, model_name=""): 40 | """Save checkpoint to the disk.""" 41 | if not osp.exists(save_dir): 42 | os.makedirs(save_dir) 43 | filename = osp.join(save_dir, model_name + ".pt") 44 | torch.save(ckpt, filename) 45 | if is_best: 46 | best_filename = osp.join(save_dir, "best_ckpt.pt") 47 | shutil.copyfile(filename, best_filename) 48 | 49 | 50 | def strip_optimizer(ckpt_dir, epoch): 51 | """Delete optimizer from saved checkpoint file""" 52 | for s in ["best", "last"]: 53 | ckpt_path = osp.join(ckpt_dir, "{}_ckpt.pt".format(s)) 54 | if not osp.exists(ckpt_path): 55 | continue 56 | ckpt = torch.load(ckpt_path, map_location=torch.device("cpu")) 57 | if ckpt.get("ema"): 58 | ckpt["model"] = ckpt["ema"] # replace model with ema 59 | for k in ["optimizer", "ema", "updates"]: # keys 60 | ckpt[k] = None 61 | ckpt["epoch"] = epoch 62 | ckpt["model"].half() # to FP16 63 | for p in ckpt["model"].parameters(): 64 | p.requires_grad = False 65 | torch.save(ckpt, ckpt_path) 66 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/utils/ema.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding:utf-8 -*- 3 | # The code is based on 4 | # https://github.com/ultralytics/yolov5/blob/master/utils/torch_utils.py 5 | import math 6 | from copy import deepcopy 7 | import torch 8 | import torch.nn as nn 9 | 10 | 11 | class ModelEMA: 12 | """Model Exponential Moving Average from https://github.com/rwightman/pytorch-image-models 13 | Keep a moving average of everything in the model state_dict (parameters and buffers). 14 | This is intended to allow functionality like 15 | https://www.tensorflow.org/api_docs/python/tf/train/ExponentialMovingAverage 16 | A smoothed version of the weights is necessary for some training schemes to perform well. 17 | This class is sensitive where it is initialized in the sequence of model init, 18 | GPU assignment and distributed training wrappers. 19 | """ 20 | 21 | def __init__(self, model, decay=0.9999, updates=0): 22 | self.ema = deepcopy( 23 | model.module if is_parallel(model) else model 24 | ).eval() # FP32 EMA 25 | self.updates = updates 26 | self.decay = lambda x: decay * (1 - math.exp(-x / 2000)) 27 | for param in self.ema.parameters(): 28 | param.requires_grad_(False) 29 | 30 | def update(self, model): 31 | with torch.no_grad(): 32 | self.updates += 1 33 | decay = self.decay(self.updates) 34 | 35 | state_dict = ( 36 | model.module.state_dict() if is_parallel(model) else model.state_dict() 37 | ) # model state_dict 38 | for k, item in self.ema.state_dict().items(): 39 | if item.dtype.is_floating_point: 40 | item *= decay 41 | item += (1 - decay) * state_dict[k].detach() 42 | 43 | def update_attr(self, model, include=(), exclude=("process_group", "reducer")): 44 | copy_attr(self.ema, model, include, exclude) 45 | 46 | 47 | def copy_attr(a, b, include=(), exclude=()): 48 | """Copy attributes from one instance and set them to another instance.""" 49 | for k, item in b.__dict__.items(): 50 | if (len(include) and k not in include) or k.startswith("_") or k in exclude: 51 | continue 52 | else: 53 | setattr(a, k, item) 54 | 55 | 56 | def is_parallel(model): 57 | """Return True if model's type is DP or DDP, else False.""" 58 | return type(model) in ( 59 | nn.parallel.DataParallel, 60 | nn.parallel.DistributedDataParallel, 61 | ) 62 | 63 | 64 | def de_parallel(model): 65 | """De-parallelize a model. Return single-GPU model if model's type is DP or DDP.""" 66 | return model.module if is_parallel(model) else model 67 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/utils/envs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import random 5 | import numpy as np 6 | 7 | import torch 8 | import torch.backends.cudnn as cudnn 9 | from yolov6.utils.events import LOGGER 10 | 11 | 12 | def get_envs(): 13 | """Get PyTorch needed environments from system envirionments.""" 14 | local_rank = int(os.getenv("LOCAL_RANK", -1)) 15 | rank = int(os.getenv("RANK", -1)) 16 | world_size = int(os.getenv("WORLD_SIZE", 1)) 17 | return local_rank, rank, world_size 18 | 19 | 20 | def select_device(device): 21 | """Set devices' information to the program. 22 | Args: 23 | device: a string, like 'cpu' or '1,2,3,4' 24 | Returns: 25 | torch.device 26 | """ 27 | if device == "cpu": 28 | os.environ["CUDA_VISIBLE_DEVICES"] = "-1" 29 | LOGGER.info("Using CPU for training... ") 30 | elif device: 31 | os.environ["CUDA_VISIBLE_DEVICES"] = device 32 | assert torch.cuda.is_available() 33 | nd = len(device.strip().split(",")) 34 | LOGGER.info(f"Using {nd} GPU for training... ") 35 | cuda = device != "cpu" and torch.cuda.is_available() 36 | device = torch.device("cuda:0" if cuda else "cpu") 37 | return device 38 | 39 | 40 | def set_random_seed(seed, deterministic=False): 41 | """Set random state to random libray, numpy, torch and cudnn. 42 | Args: 43 | seed: int value. 44 | deterministic: bool value. 45 | """ 46 | random.seed(seed) 47 | np.random.seed(seed) 48 | torch.manual_seed(seed) 49 | if deterministic: 50 | cudnn.deterministic = True 51 | cudnn.benchmark = False 52 | else: 53 | cudnn.deterministic = False 54 | cudnn.benchmark = True 55 | -------------------------------------------------------------------------------- /ev-YOLOv6/yolov6/utils/events.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import yaml 5 | import logging 6 | import shutil 7 | import wandb 8 | 9 | 10 | def set_logging(name=None): 11 | rank = int(os.getenv("RANK", -1)) 12 | logging.basicConfig( 13 | format="%(message)s", 14 | level=logging.INFO if (rank in (-1, 0)) else logging.WARNING, 15 | ) 16 | return logging.getLogger(name) 17 | 18 | 19 | LOGGER = set_logging(__name__) 20 | NCOLS = min(100, shutil.get_terminal_size().columns) 21 | 22 | 23 | def load_yaml(file_path): 24 | """Load data from yaml file.""" 25 | if isinstance(file_path, str): 26 | with open(file_path, errors="ignore") as f: 27 | data_dict = yaml.safe_load(f) 28 | return data_dict 29 | 30 | 31 | def save_yaml(data_dict, save_path): 32 | """Save data to yaml file""" 33 | with open(save_path, "w") as f: 34 | yaml.safe_dump(data_dict, f, sort_keys=False) 35 | 36 | 37 | def write_tblog(tblogger, epoch, results, losses): 38 | """Display mAP and loss information to wandb log.""" 39 | wandb.log({"val/mAP@0.5": results[0]}) 40 | wandb.log({"val/mAP@0.50:0.95": results[1]}) 41 | 42 | wandb.log({"train/iou_loss": losses[0]}) 43 | wandb.log({"train/dist_focalloss": losses[1]}) 44 | wandb.log({"train/cls_loss": losses[2]}) 45 | 46 | wandb.log({"x/lr0": results[2]}) 47 | wandb.log({"x/lr1": results[3]}) 48 | wandb.log({"x/lr2": results[4]}) 49 | 50 | 51 | def write_tbimg(tblogger, imgs, step, type="train"): 52 | """Display train_batch and validation predictions to tensorboard.""" 53 | if type == "train": 54 | tblogger.add_image(f"train_batch", imgs, step + 1, dataformats="HWC") 55 | elif type == "val": 56 | for idx, img in enumerate(imgs): 57 | wandb.log({f"val_batch/{step}/{idx + 1}": wandb.Image(img.cpu().numpy())}) 58 | # tblogger.add_image(f'val_img_{idx + 1}', img, step + 1, dataformats='HWC') 59 | else: 60 | LOGGER.warning("WARNING: Unknown image type to visualize.\n") 61 | -------------------------------------------------------------------------------- /ev-licious/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.pyc 3 | build/ 4 | *.json 5 | *.png 6 | src/evlicious.egg-info 7 | -------------------------------------------------------------------------------- /ev-licious/README.md: -------------------------------------------------------------------------------- 1 | ## Install 2 | 3 | To install type 4 | 5 | conda env create -f environment.yml 6 | conda activate evlicious 7 | pip install ev-licious/ 8 | cd ev-licious/ 9 | 10 | Optionally, to visualize event graphs also install the [ev_graph](https://github.com/uzh-rpg/ev_graph) package. 11 | 12 | ## Conversion 13 | 14 | To convert datasets use 15 | 16 | python scripts/conversion/convert_npz_to_standard_format.py path/to/folder/ --divider 1 --height 720 --width 1280 --output path/to/output.h5 17 | 18 | python scripts/conversion/convert_to_standard_format.py path/to/folder/ --recursive --divider 1 --height 720 --width 1280 --output path/to/output.h5 19 | 20 | Here only use `divider`>1 if the x and y were rescaled by a factor to remove decimal points. Most datasets use `divider`=1. 21 | 22 | ## Processing 23 | 24 | To cut events between two times run 25 | 26 | python scripts/processing/cut_events_by_time.py path/to/events.h5 --output_path path/to/output.h5 --t0_us time0 --t1_us time1 27 | 28 | To convert events to E2VID frame reconstructions, run 29 | 30 | python convert_to_video.py path/to/events.h5 --window 10000 --window_unit us --output_path path/to/output/ 31 | 32 | This script requires the `e2vid` package, which can be installed on [this page](https://github.com/uzh-rpg/e2calib). 33 | 34 | ## Visualization 35 | 36 | Test the visualization scripts with 37 | 38 | python scripts/visualization/2d_coordinate_slice_events.py tests/data/events.h5 --y_coord 120 39 | 40 | python scripts/visualization/3d_visualization_events.py tests/data/events.h5 --factor 0.002 --images tests/data/images/ --downsample_images 30 41 | 42 | python scripts/visualization/interactive_viz_events.py tests/data/events.h5 43 | 44 | python scripts/visualization/3d_animation_events_graph.py tests/data/events.h5 --delta_t_us 20000 --radius 17 45 | 46 | python scripts/visualization/half_half_rendering_events.py --images tests/data/art/images --events tests/data/art/events.h5 47 | -------------------------------------------------------------------------------- /ev-licious/environment.yml: -------------------------------------------------------------------------------- 1 | name: evlicious 2 | channels: 3 | - conda-forge 4 | - pytorch 5 | - defaults 6 | dependencies: 7 | - python=3.7 8 | - ros-sensor-msgs 9 | - ros-rosbag 10 | - ros-cv-bridge 11 | - hdf5plugin 12 | - h5py 13 | - numba 14 | - matplotlib 15 | - tqdm 16 | - pandas 17 | - open3d 18 | - plotly 19 | -------------------------------------------------------------------------------- /ev-licious/scripts/conversion/convert_to_standard_format.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | from pathlib import Path 4 | 5 | 6 | def FLAGS(): 7 | parser = argparse.ArgumentParser("""Converts .raw, .npz files to a .h5""") 8 | parser = evlicious.args.add_io_args(parser) 9 | parser.add_argument("--width", default=-1, type=int) 10 | parser.add_argument("--height", default=-1, type=int) 11 | parser.add_argument("--divider", default=1, type=int) 12 | parser.add_argument("--suffix", default="") 13 | parser.add_argument("--recursive", action="store_true") 14 | flags = parser.parse_args() 15 | assert flags.events.exists() 16 | 17 | if str(flags.output_path) == ".": 18 | flags.output_path = Path(str(flags.output_path / flags.events.name) + ".h5") 19 | 20 | return flags 21 | 22 | 23 | def convert(f, output_path, height, width, divider): 24 | handle = evlicious.io.load_events_from_path(f, height=height, width=width, divider=divider) 25 | handle.to(output_path) 26 | 27 | 28 | if __name__ == '__main__': 29 | flags = FLAGS() 30 | 31 | if flags.events.is_dir() and flags.recursive: 32 | assert flags.suffix != "" 33 | files = list(flags.events.rglob(f"*.{flags.suffix}")) 34 | with evlicious.tools.TaskManager(total=len(files)) as tm: 35 | for f in files: 36 | output_path = flags.output_path / f.relative_to(flags.events) 37 | output_path.parent.mkdir(parents=True, exist_ok=True) 38 | output_path = Path(str(output_path).replace(f".{flags.suffix}", ".h5")) 39 | tm.new_task(convert, f, output_path, flags.height, flags.width, flags.divider) 40 | else: 41 | convert(flags.events, flags.output_path, flags.height, flags.width, flags.divider) 42 | 43 | 44 | -------------------------------------------------------------------------------- /ev-licious/scripts/processing/convert_to_video.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import evlicious 4 | import e2vid 5 | import cv2 6 | 7 | 8 | def FLAGS(): 9 | parser = argparse.ArgumentParser("""Converts events to e2vid reconstruction.""") 10 | 11 | parser = evlicious.args.add_io_args(parser) 12 | parser = evlicious.args.add_filter_args(parser) 13 | 14 | parser = e2vid.options.inference_options.set_inference_options(parser) 15 | 16 | parser.add_argument("--window", type=int, default=20000, help="Window of events passed to e2vid.") 17 | parser.add_argument("--window_unit", type=str, default="us", help="Can be either 'nr' or 'us'") 18 | parser.add_argument("--clahe_tileGridSize", type=int, default=50, help="CLAHE argument") 19 | parser.add_argument("--clahe_clipLimit", type=float, default=2.0, help="CLAHE argument") 20 | 21 | flags = parser.parse_args() 22 | assert flags.events.exists() 23 | 24 | if str(flags.output_path) == ".": 25 | flags.output_path = flags.output_path / flags.events.name 26 | 27 | return flags 28 | 29 | 30 | if __name__ == '__main__': 31 | flags = FLAGS() 32 | 33 | events = evlicious.io.load_events_from_path(flags.events) 34 | #filter = evlicious.tools.filters.from_flags(flags) 35 | 36 | # e2vid flags expect to know the shape of the sensor 37 | flags.height = events.height 38 | flags.width = events.width 39 | 40 | model = e2vid.E2VID(flags) 41 | 42 | if not flags.output_path.exists(): 43 | flags.output_path.mkdir(exist_ok=True) 44 | 45 | clahe = None 46 | #if flags.clahe_clipLimit > 0: 47 | # clahe = cv2.createCLAHE(clipLimit=flags.clahe_clipLimit, tileGridSize=(flags.clahe_tileGridSize, flags.clahe_tileGridSize)) 48 | 49 | counter = 0 50 | timestamps_file = flags.output_path / "timestamps.txt" 51 | if timestamps_file.exists(): 52 | timestamps_file.remove() 53 | 54 | for ev in events.iterator(step_size=flags.window, window=flags.window, window_unit=flags.window_unit, step_size_unit=flags.window_unit, pbar=True): 55 | t_event = ev.t[-1] 56 | #ev = filter.insert(ev) 57 | 58 | voxel_grid = evlicious.tools.events_to_voxel_grid_cuda(ev, num_bins=5, normalize=not flags.no_normalize, device="cuda:0") 59 | reconstruction = model(voxel_grid) 60 | 61 | if clahe is not None: 62 | reconstruction = clahe.apply(reconstruction) 63 | 64 | if False: 65 | output_path = flags.output_path / ("%05d.png" % counter) 66 | cv2.imwrite(str(output_path), reconstruction) 67 | counter += 1 68 | 69 | with open(str(timestamps_file), "a") as fh: 70 | fh.write(f"{t_event}\n") 71 | -------------------------------------------------------------------------------- /ev-licious/scripts/processing/cut_events_by_time.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import evlicious 4 | 5 | 6 | def FLAGS(): 7 | parser = argparse.ArgumentParser("""Cuts events between t0_us and t1_us""") 8 | parser = evlicious.args.add_io_args(parser) 9 | 10 | parser.add_argument("--t0_us", type=int, default=-1) 11 | parser.add_argument("--t1_us", type=int, default=-1) 12 | 13 | flags = parser.parse_args() 14 | assert flags.events.exists() 15 | 16 | if str(flags.output_path) == ".": 17 | flags.output_path = flags.output_path / flags.events.name 18 | 19 | return flags 20 | 21 | 22 | if __name__ == '__main__': 23 | flags = FLAGS() 24 | 25 | events = evlicious.io.load_events_from_path(flags.events) 26 | events = events.get_between_time(flags.t0_us, flags.t1_us) 27 | events.to(flags.output_path) 28 | -------------------------------------------------------------------------------- /ev-licious/scripts/processing/filter_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | 4 | 5 | def FLAGS(): 6 | parser = argparse.ArgumentParser("""Filters events""") 7 | parser = evlicious.args.add_io_args(parser) 8 | parser = evlicious.args.add_filter_args(parser) 9 | 10 | flags = parser.parse_args() 11 | assert flags.events.exists() 12 | 13 | if str(flags.output_path) == ".": 14 | flags.output_path = flags.output_path / flags.events.name 15 | 16 | return flags 17 | 18 | 19 | if __name__ == '__main__': 20 | flags = FLAGS() 21 | events = evlicious.io.load_events_from_path(flags.events) 22 | 23 | filter = evlicious.tools.filters.from_flags(flags) 24 | 25 | writer = evlicious.io.H5Writer(flags.output_path) 26 | for ev in events.iterator(step_size=1000000, step_size_unit="nr", window=1000000, window_unit="nr", pbar=True): 27 | ev_filtered = filter.insert(ev) 28 | writer.add_data(ev_filtered) 29 | 30 | idx = 1000000 * (len(events) // 1000000) 31 | ev = events.get_between_idx(idx, len(events)) 32 | ev_filtered = filter.insert(ev) 33 | writer.add_data(ev_filtered) 34 | -------------------------------------------------------------------------------- /ev-licious/scripts/processing/resize_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | import tqdm 4 | 5 | 6 | if __name__ == '__main__': 7 | parser = argparse.ArgumentParser("""Downsample events""") 8 | parser = evlicious.args.add_io_args(parser) 9 | parser.add_argument("--output_height", type=int, default=180) 10 | parser.add_argument("--output_width", type=int, default=320) 11 | args = parser.parse_args() 12 | 13 | events = evlicious.io.load_events_from_path(args.events) 14 | downsampled = evlicious.tools.resize_to_resolution(events, height=args.output_height, width=args.output_width, chunks=100, pbar=tqdm.tqdm(total=100)) 15 | if args.output_path != ".": 16 | evlicious.io.save_events(args.output_path, downsampled) 17 | 18 | -------------------------------------------------------------------------------- /ev-licious/scripts/processing/write_events_to_rosbag.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | 4 | try: 5 | import rosbag 6 | except ImportError: 7 | print("Cannot use ros api") 8 | 9 | 10 | def FLAGS(): 11 | parser = argparse.ArgumentParser("""Write events to a rosbag""") 12 | parser = evlicious.args.add_io_args(parser) 13 | parser.add_argument("--framerate", type=int, default=30, help=f"framerate of the event arrays in the output rosbag") 14 | 15 | # background activity filter 16 | parser.add_argument("--topic", type=str, default="/dvs/events") 17 | 18 | flags = parser.parse_args() 19 | assert flags.events.exists() 20 | 21 | if str(flags.output_path) == ".": 22 | flags.output_path = flags.output_path / flags.events.name 23 | 24 | return flags 25 | 26 | 27 | if __name__ == '__main__': 28 | flags = FLAGS() 29 | events = evlicious.io.load_events_from_path(flags.events) 30 | 31 | delta_t_us = int(1e6 / flags.framerate) 32 | t_min_us, t_max_us = events.get_time_limits() 33 | total = (t_max_us - t_min_us) // delta_t_us 34 | 35 | rosbag_flag = "a" if flags.output_path.exists() else "w" 36 | 37 | with evlicious.tools.task_manager.TaskManager(total=total) as tm: 38 | for ev in events.iterator(step_size=delta_t_us, step_size_unit="us", window=delta_t_us, window_unit="us", pbar=False): 39 | if len(ev) > 0: 40 | tm.new_task(evlicious.io.events_to_ros_message, ev) 41 | else: 42 | tm.pbar.update(1) 43 | 44 | with rosbag.Bag(flags.output_path, mode=rosbag_flag) as bag: 45 | for msg in tm.outputs: 46 | bag.write(flags.topic, msg, msg.header.stamp) 47 | 48 | -------------------------------------------------------------------------------- /ev-licious/scripts/processing/write_images_to_rosbag.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | try: 4 | import rosbag 5 | from cv_bridge import CvBridge 6 | import rospy 7 | except ImportError: 8 | print("Cannot use ros api") 9 | 10 | 11 | import numpy as np 12 | import cv2 13 | 14 | 15 | def FLAGS(): 16 | parser = argparse.ArgumentParser("""Write images to a rosbag""") 17 | parser = evlicious.args.add_io_args(parser) 18 | 19 | parser.add_argument("--topic", type=str, default="/dvs/reconstruction") 20 | 21 | flags = parser.parse_args() 22 | assert flags.events.exists() 23 | 24 | if str(flags.output_path) == ".": 25 | flags.output_path = flags.output_path / flags.events.name 26 | 27 | return flags 28 | 29 | 30 | if __name__ == '__main__': 31 | flags = FLAGS() 32 | bridge = CvBridge() 33 | images = sorted(list(flags.events.rglob("*.png"))) 34 | timestamps_us = np.genfromtxt(flags.events / "timestamps.txt") 35 | rosbag_flag = "a" if flags.output_path.exists() else "w" 36 | 37 | with rosbag.Bag(flags.output_path, mode=rosbag_flag) as bag: 38 | for img_path, t_us in zip(images, timestamps_us): 39 | img = cv2.imread(str(img_path), cv2.IMREAD_GRAYSCALE) 40 | msg = bridge.cv2_to_imgmsg(img, "mono8") 41 | t_ros = rospy.Time.from_seconds(t_us/1e6) 42 | msg.header.stamp = t_ros 43 | bag.write(flags.topic, msg, t_ros) 44 | 45 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/2d_coordinate_slice_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import matplotlib.pyplot as plt 3 | import evlicious 4 | 5 | 6 | def FLAGS(): 7 | parser = argparse.ArgumentParser(description='''Visualize event slice in 2D''') 8 | parser = evlicious.args.add_io_args(parser) 9 | parser.add_argument('--height', type=int, help='Height in pixels.', default=-1) 10 | parser.add_argument('--width', type=int, help='Width in pixels.', default=-1) 11 | parser.add_argument('--y_coord', type=int, default=-1) 12 | parser.add_argument('--x_coord', type=int, default=-1) 13 | 14 | return parser.parse_args() 15 | 16 | 17 | if __name__ == "__main__": 18 | args = FLAGS() 19 | events = evlicious.io.load_events_from_path(args.events).load() 20 | 21 | fig, ax = plt.subplots() 22 | if args.y_coord > 0: 23 | evlicious.art.plot_y_slice(ax, events, args.y_coord) 24 | if args.x_coord > 0: 25 | evlicious.art.plot_x_slice(ax, events, args.x_coord) 26 | 27 | plt.show() 28 | 29 | 30 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/3d_animation_events_graph.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from pathlib import Path 3 | import evlicious 4 | import ev_graph 5 | import torch 6 | 7 | 8 | def FLAGS(): 9 | parser = argparse.ArgumentParser(description='''Generate event graph animation.''') 10 | parser = evlicious.args.add_io_args(parser) 11 | parser.add_argument('--height', type=int, help='Height.', default=-1) 12 | parser.add_argument('--width', type=int, help='Width.', default=-1) 13 | parser.add_argument('--downsample_events', type=int, help='Downsample number.', default=1) 14 | parser.add_argument('--radius', type=float, help='Downsample number.', default=3) 15 | parser.add_argument('--delta_t_us', type=int, help='Downsample number.', default=300000) 16 | parser.add_argument('--t_step_us', type=int, help='Downsample number.', default=3000) 17 | parser.add_argument('--max_num_neighbors', type=int, help='Downsample number.', default=16) 18 | 19 | parser.add_argument('--front_side', action="store_true", help='Front side projection of events.') 20 | 21 | return parser.parse_args() 22 | 23 | 24 | if __name__ == "__main__": 25 | args = FLAGS() 26 | args.width = args.width if args.width > 0 else None 27 | args.height = args.height if args.height > 0 else None 28 | events = evlicious.io.load_events_from_path(args.events, height=args.height, width=args.width) 29 | 30 | graph = ev_graph.AsyncGraph(width=events.width, 31 | height=events.height, 32 | delta_t_us=args.delta_t_us, 33 | radius=args.radius, 34 | max_num_neighbors=args.max_num_neighbors) 35 | 36 | factor = args.radius / args.delta_t_us 37 | visualizer = evlicious.art.EventGraphVisualizer(events) 38 | visualizer.run(args.output_path, 39 | args.delta_t_us, 40 | args.t_step_us, 41 | args.radius, 42 | args.max_num_neighbors, 43 | args.downsample_events, 44 | args.front_side) 45 | 46 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/3d_animation_voxel_grid.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | 4 | 5 | def FLAGS(): 6 | parser = argparse.ArgumentParser(description='''Generate event graph animation.''') 7 | parser = evlicious.args.add_io_args(parser) 8 | parser.add_argument('--n_events_window', type=int, help='Downsample number.', default=300000) 9 | parser.add_argument('--n_events_step', type=int, help='Downsample number.', default=3000) 10 | return parser.parse_args() 11 | 12 | 13 | if __name__ == "__main__": 14 | args = FLAGS() 15 | events = evlicious.io.load_events_from_path(args.events) 16 | events.height = 636+1 17 | events.width = 966+1 18 | 19 | visualizer = evlicious.art.O3DVoxelGridVisualizer(events, factor=1) 20 | visualizer.loop(args.output_path, n_events_window=args.n_events_window, n_events_step=args.n_events_step) 21 | 22 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/3d_visualization_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | from evlicious.io.utils.load_data import load_images, load_feature_tracks 4 | 5 | 6 | def main(): 7 | parser = argparse.ArgumentParser(description='''Generate 3D X-Y-T event plots and optionally also visualize feature tracks''') 8 | parser = evlicious.args.add_io_args(parser) 9 | parser.add_argument('--images', help='Image folder.', default="") 10 | parser.add_argument('--tracks', help='Path to csv of feature tracks.', default="") 11 | parser.add_argument('--downsample_images', type=int, help='Downsample images by.', default=1) 12 | parser.add_argument('--downsample_events', type=int, help='Downsample events by.', default=1) 13 | parser.add_argument('--time_scaling_factor', type=float, help='Scale time in us by this factor.', default=0.02) 14 | parser.add_argument('--start_time', type=int, help='Render events from time.', default=-1) 15 | parser.add_argument('--end_time', type=int, help='Render events to time.', default=-1) 16 | parser.add_argument('--loop', action="store_true") 17 | parser.add_argument('--time_step_us', type=int, help="Time step each iteration, in us", default=1000) 18 | parser.add_argument('--time_window_us', type=int, help="Time window in us", default=100000) 19 | args = parser.parse_args() 20 | 21 | event_handle = evlicious.io.load_events_from_path(args.events) 22 | 23 | t0, t1 = event_handle.get_time_limits() 24 | args.start_time = t0 if args.start_time < 0 else args.start_time 25 | args.end_time = t1 if args.end_time < 0 else args.end_time 26 | events = event_handle.get_between_time(args.start_time, args.end_time) 27 | events = events[::args.downsample_events] 28 | print("Event timestamps: ", events.t[0], events.t[-1]) 29 | 30 | # if images are given, load them 31 | image_data = load_images(args.images, args.downsample_images) 32 | tracks_data = load_feature_tracks(args.tracks) 33 | 34 | evlicious.art.visualize_3d(events, time_window_us=args.time_window_us, 35 | time_step_us=args.time_step_us, 36 | images=image_data, 37 | factor=args.time_scaling_factor, 38 | tracks=tracks_data, 39 | output_path=args.output_path, 40 | loop=args.loop) 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | 46 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/event_rate_visualialization.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | from evlicious.io.utils.load_data import load_images, load_feature_tracks 6 | 7 | 8 | def main(): 9 | parser = argparse.ArgumentParser(description='''Generate 3D X-Y-T event plots and optionally also visualize feature tracks''') 10 | parser = evlicious.args.add_io_args(parser) 11 | parser.add_argument('--time_window_us', type=int, help="Time window in us", default=100000) 12 | parser.add_argument('--time_step_us', type=int, help="Time window in us", default=10000) 13 | args = parser.parse_args() 14 | 15 | event_handle = evlicious.io.load_events_from_path(args.events) 16 | _, (idx0, idx1) = event_handle.compute_time_and_index_windows(step_size=args.time_step_us, window=args.time_window_us, step_size_unit="us", window_unit="us") 17 | rate_mhz = (idx1 - idx0) / args.time_window_us 18 | 19 | fig, ax = plt.subplots() 20 | t0, t1 = event_handle.get_time_limits() 21 | timestamps = np.linspace(t0, t1, len(rate_mhz)) - t0 22 | ax.plot(timestamps, rate_mhz) 23 | ax.set_xlabel("Time [us]") 24 | ax.set_ylabel("Event Rate [MHz]") 25 | plt.show() 26 | 27 | if __name__ == "__main__": 28 | main() 29 | 30 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/events_to_rendering.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import evlicious 4 | import cv2 5 | 6 | 7 | if __name__ == "__main__": 8 | parser = argparse.ArgumentParser("""Visualize Events Interactively""") 9 | parser = evlicious.args.add_io_args(parser) 10 | parser.add_argument("--width", type=int, default=-1) 11 | parser.add_argument("--height", type=int, default=-1) 12 | parser.add_argument("--time_step_us", type=int, default=10000) 13 | parser.add_argument("--time_window_us", type=int, default=40000) 14 | 15 | args = parser.parse_args() 16 | 17 | args.width = args.width if args.width > 0 else None 18 | args.height = args.height if args.height > 0 else None 19 | handle = evlicious.io.load_events_from_path(args.events, height=args.height, width=args.width) 20 | 21 | if not args.output_path.exists(): 22 | args.output_path.mkdir() 23 | 24 | counter = 0 25 | for events in handle.iterator(step_size=args.time_step_us, window=args.time_window_us, step_size_unit="us", window_unit="us", pbar=True): 26 | image = events.render(cast=False, rendering_type=evlicious.RenderingType.RED_BLUE_NO_OVERLAP) 27 | cv2.imwrite(str(args.output_path / ("%05d.png" % counter)), image) 28 | counter += 1 29 | 30 | -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/half_half_rendering_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import numpy as np 3 | import cv2 4 | import glob 5 | import matplotlib.pyplot as plt 6 | from os.path import join 7 | 8 | import evlicious 9 | 10 | 11 | def FLAGS(): 12 | parser = argparse.ArgumentParser(description='''Blend together events and frames.''') 13 | parser = evlicious.args.add_io_args(parser) 14 | parser.add_argument('--images', help='Root of folder with images.', default="") 15 | parser.add_argument('--height', type=int, help='Height.', default=-1) 16 | parser.add_argument('--width', type=int, help='Width.', default=-1) 17 | parser.add_argument('--t_window_us', type=int, help='Time window in microseconds.', default=10000) 18 | parser.add_argument('--blending_scale', type=float, help='Blending scale.', default=0.02) 19 | 20 | return parser.parse_args() 21 | 22 | 23 | if __name__ == "__main__": 24 | args = FLAGS() 25 | args.width = args.width if args.width > 0 else None 26 | args.height = args.height if args.height > 0 else None 27 | 28 | # load images 29 | images = sorted(glob.glob(join(args.images, "*.jpg"))) 30 | image_stamps = np.genfromtxt(join(args.images, "timestamps.txt")) 31 | 32 | events = evlicious.io.load_events_from_path(args.events) 33 | 34 | t0_ms = image_stamps[len(image_stamps) // 2] 35 | events = events.get_between_time(t0_ms, t0_ms + args.t_window_us) 36 | image = cv2.imread(images[len(image_stamps) // 2]) 37 | 38 | event_rendering = events.render() 39 | print(event_rendering) 40 | output = evlicious.art.blend_images(image, event_rendering, args.blending_scale)[...,::-1] 41 | 42 | plt.imshow(output) 43 | plt.show() -------------------------------------------------------------------------------- /ev-licious/scripts/visualization/interactive_viz_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import evlicious 3 | 4 | 5 | if __name__ == "__main__": 6 | parser = argparse.ArgumentParser("""Visualize Events Interactively""") 7 | parser = evlicious.args.add_io_args(parser) 8 | parser.add_argument("--width", type=int, default=-1) 9 | parser.add_argument("--height", type=int, default=-1) 10 | args = parser.parse_args() 11 | 12 | args.width = args.width if args.width > 0 else None 13 | args.height = args.height if args.height > 0 else None 14 | evlicious.io.load_events_from_path(args.events, height=args.height, width=args.width).interactive_viz_loop() 15 | -------------------------------------------------------------------------------- /ev-licious/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='evlicious', 5 | version='0.1', 6 | packages=['evlicious', 7 | 'evlicious/io', 8 | 'evlicious/tools', 9 | 'evlicious/art', 10 | 'evlicious/io/utils', 11 | 'evlicious/io/utils/dvs_msgs'], 12 | package_dir={'':'src'} 13 | ) 14 | -------------------------------------------------------------------------------- /ev-licious/src/evlicious/__init__.py: -------------------------------------------------------------------------------- 1 | from . import io 2 | from .io.utils.events import Events 3 | from . import art 4 | from . import tools 5 | from . import args 6 | from .io.utils.render import RenderingType -------------------------------------------------------------------------------- /ev-licious/src/evlicious/args.py: -------------------------------------------------------------------------------- 1 | import evlicious 2 | from pathlib import Path 3 | 4 | 5 | def add_io_args(parser): 6 | parser.add_argument('events', help='Root of folder with events.', type=Path, default="") 7 | parser.add_argument("--output_path", type=Path, default="") 8 | return parser 9 | 10 | def add_filter_args(parser): 11 | filtering_types = evlicious.tools.filters.Filtering_Type.summary() 12 | parser.add_argument("--filter_type", type=int, default=-1, help=f"Has to be one of the following: {filtering_types}.") 13 | 14 | # background activity filter 15 | parser.add_argument("--depth_us", type=int, default=-1) 16 | parser.add_argument("--radius", type=int, default=-1) 17 | 18 | # ContrastThresholdIncrease 19 | parser.add_argument("--contrast_threshold_multiplier", type=int, default=-1) 20 | 21 | # random 22 | parser.add_argument("--random_downsampling_factor", type=int, default=-1) 23 | 24 | return parser -------------------------------------------------------------------------------- /ev-licious/src/evlicious/art/__init__.py: -------------------------------------------------------------------------------- 1 | from .utils import * 2 | from .o3d_vis import * -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/__init__.py: -------------------------------------------------------------------------------- 1 | from .h5_event_handle import H5EventHandle 2 | from .npz_event_handle import NPZEventHandle 3 | from .npy_event_handle import NPYEventHandle 4 | from .dat_event_handle import DatEventHandle 5 | 6 | try: 7 | from .rosbag_event_handle import RosbagEventHandle 8 | from .utils.rosbag import events_to_ros_message 9 | except ImportError: 10 | print("Cannot use ros api") 11 | 12 | from .utils.h5_writer import H5Writer, H5_BLOSC_COMPRESSION_FLAGS 13 | from .utils.fake_events import generate_fake_events 14 | from .bin_event_handle import BinEventHandle 15 | from pathlib import Path 16 | 17 | 18 | def load_events_from_path(path: Path, height=None, width=None, divider=1): 19 | if path.suffix == ".h5": 20 | return H5EventHandle.from_path(path) 21 | elif path.suffix == ".dat": 22 | return DatEventHandle.from_path(path) 23 | elif path.suffix == ".bag": 24 | return RosbagEventHandle.from_path(path) 25 | elif path.suffix == ".bin": 26 | return BinEventHandle.from_path(path, height, width, divider) 27 | elif path.is_dir(): 28 | for f in path.iterdir(): 29 | if f.is_file(): 30 | if f.suffix == ".npz": 31 | return NPZEventHandle.from_path(path, height=height, width=width, divider=divider) 32 | elif f.suffix == ".npy": 33 | return NPYEventHandle.from_path(path, height=height, width=width, divider=divider) 34 | else: 35 | raise ValueError 36 | 37 | def save_events(path, events): 38 | writer = H5Writer(path) 39 | writer.add_data(events) 40 | 41 | 42 | -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/bin_event_handle.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import numpy as np 3 | 4 | from .utils.event_handle import EventHandle 5 | from .utils.events import Events 6 | from .h5_event_handle import _find_index_from_timestamps 7 | 8 | 9 | class DataEventHandle(EventHandle): 10 | def __init__(self, data, height, width, divider=1): 11 | self.height = height 12 | self.width = width 13 | 14 | self.divider = divider 15 | self.data = data 16 | 17 | def get_between_idx(self, i0, i1): 18 | return Events.from_array(self.data[i0:i1], height=self.height, width=self.width, divider=self.divider) 19 | 20 | def get_between_time(self, t0_us: int, t1_us: int): 21 | t = self.data[:,2] 22 | idx0 = _find_index_from_timestamps(t0_us, t) 23 | idx1 = _find_index_from_timestamps(t1_us, t) 24 | return self.get_between_idx(idx0, idx1) 25 | 26 | def __len__(self): 27 | return len(self.data) 28 | 29 | 30 | class BinEventHandle(DataEventHandle): 31 | @classmethod 32 | def from_path(cls, path: Path, height, width, divider=1): 33 | data = load_bin(path) 34 | return DataEventHandle(data, height=height, width=width, divider=divider) 35 | 36 | 37 | def load_bin(path: Path) -> np.array: 38 | f = open(str(path), 'rb') 39 | raw_data = np.fromfile(f, dtype=np.uint8) 40 | f.close() 41 | 42 | raw_data = np.uint32(raw_data) 43 | all_y = raw_data[1::5] 44 | all_x = raw_data[0::5] 45 | all_p = (raw_data[2::5] & 128) >> 7 # bit 7 46 | all_ts = ((raw_data[2::5] & 127) << 16) | (raw_data[3::5] << 8) | (raw_data[4::5]) 47 | all_p = all_p.astype(np.float64) 48 | all_p[all_p == 0] = -1 49 | events = np.column_stack((all_x, all_y, all_ts, all_p)) 50 | 51 | return events 52 | -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/dat_event_handle.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import sys 3 | sys.path.append("/usr/lib/python3/dist-packages/") 4 | 5 | from .utils.prophesee_utils import _cd_events_to_standard_format, EventDatReader 6 | from .utils.event_handle import EventHandle 7 | 8 | 9 | class DatEventHandle(EventHandle): 10 | def __init__(self, reader, height, width, divider=1, strict=True): 11 | self.height = height 12 | self.width = width 13 | 14 | self.divider = divider 15 | self.strict = strict 16 | self.reader = reader 17 | 18 | @classmethod 19 | def from_path(cls, path: Path, **kwargs): 20 | reader = EventDatReader(str(path)) 21 | height, width = reader.get_size() 22 | return cls(reader, height=height, width=width, divider=1, **kwargs) 23 | 24 | def get_between_idx(self, i0, i1): 25 | self.reader.seek_event(i0) 26 | events = self.reader.load_n_events(i1 - i0) 27 | return _cd_events_to_standard_format(events, self.height, self.width) 28 | 29 | def get_between_time(self, t0_us: int, t1_us: int): 30 | self.reader.seek_time(t0_us) 31 | events = self.reader.load_delta_t(t1_us - t0_us) 32 | return _cd_events_to_standard_format(events, self.height, self.width) 33 | 34 | def __len__(self): 35 | return self.reader.event_count() 36 | -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/npy_event_handle.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from .utils import event_handle 3 | from .utils.events import Events 4 | import glob 5 | 6 | import numpy as np 7 | import evlicious 8 | 9 | 10 | def npz_len(npz): 11 | """ 12 | Takes a path to an .npz file, which is a Zip archive of .npy files. 13 | Generates a sequence of (name, shape, np.dtype). 14 | """ 15 | return len(np.load(npz)) 16 | 17 | 18 | class NPYEventHandle(event_handle.EventHandle): 19 | def __init__(self, files, height, width, divider=1, strict=True): 20 | self.height = height 21 | self.width = width 22 | self.files = files 23 | self.divider = divider 24 | self.strict = strict 25 | 26 | self.files = [f for f in self.files if npz_len(f) > 0] 27 | self.npz_lens = np.array([npz_len(f) for f in self.files]) 28 | self.npz_times = np.array([np.load(f)[-1,2]//1e3 for f in self.files]) 29 | self.npz_cumsum = np.cumsum(self.npz_lens) 30 | 31 | def _npy_to_events(self, file, height, width, divider=1): 32 | fh = np.load(file) 33 | x, y, t, p = fh.T 34 | p[p==0] = -1 35 | t = (t // 1000).astype("int64") 36 | 37 | return Events(x=x.astype("uint16"), 38 | y=y.astype("uint16"), 39 | t=t, 40 | p=p.astype("int8"), 41 | width=width, 42 | height=height, 43 | divider=divider) 44 | 45 | def get_time_limits(self): 46 | return np.load(self.files[0])[0,2]//1e3, np.load(self.files[-1])[-1,2]//1e3 47 | 48 | @classmethod 49 | def from_path(cls, path: Path, height, width, **kwargs): 50 | files = sorted(glob.glob(str(path / "*.npy"))) 51 | return cls(files, height=height, width=width, **kwargs) 52 | 53 | def get_between_idx(self, i0, i1): 54 | idx0 = np.searchsorted(self.npz_cumsum, i0) 55 | idx1 = np.searchsorted(self.npz_cumsum, i1) 56 | 57 | events = evlicious.tools.stack([self._npy_to_events(self.files[i], height=self.height, 58 | width=self.width, divider=self.divider) for 59 | i in range(idx0, idx1+1)]) 60 | offset = (self.npz_cumsum[idx0-1] if idx0 > 0 else 0) 61 | i0 -= offset 62 | i1 -= offset 63 | 64 | return events[i0:i1] 65 | 66 | def get_between_time(self, t0_us: int, t1_us: int): 67 | idx0 = np.searchsorted(self.npz_times, t0_us) 68 | idx1 = np.searchsorted(self.npz_times, t0_us) 69 | events = evlicious.tools.stack([self._npy_to_events(self.files[i], height=self.height, 70 | width=self.width, divider=self.divider) for 71 | i in range(idx0, idx1 + 1)]) 72 | return events[(events.t <= t1_us) & (events.t >= t0_us)] 73 | 74 | def __len__(self): 75 | return self.npz_cumsum[-1] 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from . import event_handle -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/utils/event_handle.py: -------------------------------------------------------------------------------- 1 | import abc 2 | from pathlib import Path 3 | import numpy as np 4 | import tqdm 5 | 6 | from .h5_writer import H5Writer 7 | from .visualization import Visualizer 8 | 9 | 10 | class EventHandle: 11 | @classmethod 12 | @abc.abstractmethod 13 | def from_path(cls, path: Path, height=None, width=None): 14 | raise NotImplemented 15 | 16 | @abc.abstractmethod 17 | def get_between_time(self, t0_us: int, t1_us: int): 18 | raise NotImplemented 19 | 20 | @abc.abstractmethod 21 | def get_between_idx(self, i0, i1): 22 | raise NotImplemented 23 | 24 | @abc.abstractmethod 25 | def compute_time_and_index_windows(self, step_size: int, window: int, step_size_unit: str, window_unit: str): 26 | raise NotImplemented 27 | 28 | @abc.abstractmethod 29 | def __len__(self): 30 | raise NotImplemented 31 | 32 | def to(self, path: Path): 33 | window_size = 100000 34 | writer = H5Writer(path) 35 | 36 | idx = np.arange(0, len(self), window_size).tolist() + [len(self)] 37 | idx0, idx1 = idx[:-1], idx[1:] 38 | for (i0_, i1_) in zip(idx0, idx1): 39 | events = self.get_between_idx(i0_, i1_) 40 | writer.add_data(events) 41 | 42 | def __getitem__(self, item: slice): 43 | assert type(item) is slice 44 | assert item.step is None 45 | return self.get_between_idx(item.start, item.stop) 46 | 47 | def interactive_viz_loop(self): 48 | visualizer = Visualizer(self) 49 | visualizer.visualizationLoop() 50 | 51 | def iterator(self, step_size: int, window: int, step_size_unit: str, window_unit: str, pbar=False): 52 | _, (idx0, idx1) = self.compute_time_and_index_windows(step_size, window, step_size_unit, window_unit) 53 | if pbar: 54 | pbar = tqdm.tqdm(total=len(idx0)) 55 | for (i0_, i1_) in zip(idx0, idx1): 56 | if pbar: 57 | pbar.update(1) 58 | yield self.get_between_idx(i0_, i1_) 59 | 60 | def load(self): 61 | return self.get_between_idx(0, len(self)) 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/utils/fake_events.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from .events import Events 3 | 4 | 5 | def generate_fake_events(optical_flow=(10, 0), N=10000, circle_radius=5, starting_point=(10,10), resolution=(30,30)): 6 | """ 7 | optical flow: 2 numbers, vx, vy denoting the flow in x and y direction. 8 | N: Number of events 9 | Example: 10 | events = optical_flow([5, 6], 10000) 11 | """ 12 | vx, vy = optical_flow 13 | 14 | # sample t and angle from uniform distribution 15 | time = np.sort(np.random.random((N,))).reshape((N,1)) 16 | angle = np.random.random((N,1)) * 2*np.pi 17 | polarity = 2*(np.random.random((N,1)) > .5)-1 18 | 19 | # compute coordinates 20 | u0, v0 = starting_point 21 | x = (u0 + time * vx + np.cos(angle) * circle_radius).astype(np.int64) 22 | y = (v0 + time * vy + np.sin(angle) * circle_radius).astype(np.int64) 23 | 24 | # compute mask for events that are within image 25 | H, W = resolution 26 | mask = (x[:,0] >= 0) & (y[:,0] >= 0) & (x[:,0] < W) & (y[:,0] < H) 27 | 28 | events = np.concatenate([x[mask, :], y[mask, :], 1e6*time[mask, :], polarity[mask, :]], 1) 29 | 30 | return Events.from_array(events, format="xytp") -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/utils/h5_writer.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import weakref 3 | 4 | import h5py 5 | 6 | from .events import Events 7 | 8 | def _compression_opts(): 9 | compression_level = 1 # {0, ..., 9} 10 | shuffle = 2 # {0: none, 1: byte, 2: bit} 11 | # From https://github.com/Blosc/c-blosc/blob/7435f28dd08606bd51ab42b49b0e654547becac4/blosc/blosc.h#L66-L71 12 | # define BLOSC_BLOSCLZ 0 13 | # define BLOSC_LZ4 1 14 | # define BLOSC_LZ4HC 2 15 | # define BLOSC_SNAPPY 3 16 | # define BLOSC_ZLIB 4 17 | # define BLOSC_ZSTD 5 18 | compressor_type = 5 19 | compression_opts = (0, 0, 0, 0, compression_level, shuffle, compressor_type) 20 | return compression_opts 21 | 22 | H5_BLOSC_COMPRESSION_FLAGS = dict( 23 | compression=32001, 24 | compression_opts=_compression_opts(), # Blosc 25 | chunks=True 26 | ) 27 | 28 | 29 | class H5Writer: 30 | def __init__(self, outfile: Path): 31 | assert not outfile.exists(), str(outfile) 32 | self.h5f = h5py.File(str(outfile), 'w') 33 | self._finalizer = weakref.finalize(self, self.close_callback, self.h5f) 34 | 35 | # create hdf5 datasets 36 | shape = (2**16,) 37 | maxshape = (None,) 38 | self.h5f.create_dataset('events/x', shape=shape, dtype='u2', maxshape=maxshape, **H5_BLOSC_COMPRESSION_FLAGS) 39 | self.h5f.create_dataset('events/y', shape=shape, dtype='u2', maxshape=maxshape, **H5_BLOSC_COMPRESSION_FLAGS) 40 | self.h5f.create_dataset('events/p', shape=shape, dtype='i1', maxshape=maxshape, **H5_BLOSC_COMPRESSION_FLAGS) 41 | self.h5f.create_dataset('events/t', shape=shape, dtype='i8', maxshape=maxshape, **H5_BLOSC_COMPRESSION_FLAGS) 42 | self.row_idx = 0 43 | self.first = True 44 | 45 | @staticmethod 46 | def close_callback(h5f: h5py.File): 47 | h5f.close() 48 | 49 | def add_data(self, events: Events): 50 | if self.first: 51 | self.h5f.create_dataset('events/width', data=events.width, dtype='i4') 52 | self.h5f.create_dataset('events/height', data=events.height, dtype='i4') 53 | self.h5f.create_dataset('events/divider', data=events.divider, dtype='i4') 54 | self.first = False 55 | 56 | current_size = len(events) 57 | new_size = self.row_idx + current_size 58 | self.h5f['events/x'].resize(new_size, axis=0) 59 | self.h5f['events/y'].resize(new_size, axis=0) 60 | self.h5f['events/p'].resize(new_size, axis=0) 61 | self.h5f['events/t'].resize(new_size, axis=0) 62 | 63 | self.h5f['events/x'][self.row_idx:new_size] = events._x 64 | self.h5f['events/y'][self.row_idx:new_size] = events._y 65 | self.h5f['events/p'][self.row_idx:new_size] = events.p 66 | self.h5f['events/t'][self.row_idx:new_size] = events.t 67 | 68 | self.row_idx = new_size -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/utils/load_data.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | import glob 4 | 5 | 6 | def load_images(path, downsample_factor): 7 | if path == "": 8 | return {} 9 | image_files = sorted(glob.glob(os.path.join(path, "*.jpg"))) 10 | image_timestamps = np.genfromtxt(os.path.join(path, "timestamps.txt")) 11 | mean_dt = np.diff(image_timestamps).mean() 12 | if mean_dt < 1: # is s 13 | image_timestamps *= 1e6 14 | if mean_dt > 1e5: # is ns 15 | image_timestamps /= 1e3 16 | return dict(files=image_files[::downsample_factor], 17 | timestamps=image_timestamps[::downsample_factor]) 18 | 19 | def load_feature_tracks(path): 20 | if path == "": 21 | return {} 22 | tracks = np.genfromtxt(path, delimiter=",", dtype="float64") 23 | tracks_data = {i: tracks[tracks[:, 0] == i][:, [2, 3, 1]] for i in np.unique(tracks[:, 0])} 24 | for i in tracks_data: 25 | tracks_data[i][:, 2] *= 1e6 26 | return {i: track for i, track in tracks_data.items() if len(track) > 2} -------------------------------------------------------------------------------- /ev-licious/src/evlicious/io/utils/rosbag.py: -------------------------------------------------------------------------------- 1 | import rospy 2 | from .events import Events 3 | from .dvs_msgs._Event import Event 4 | from .dvs_msgs._EventArray import EventArray 5 | 6 | 7 | def _us_to_rostime(t_us): 8 | return rospy.Time.from_seconds(t_us / 1e6) 9 | 10 | def _event_to_event_msg(event): 11 | x,y,t,p = event 12 | return Event(x=x, y=y, ts=_us_to_rostime(t), polarity=p==1) 13 | 14 | def events_to_ros_message(events: Events, seq=0) -> EventArray: 15 | array = EventArray() 16 | array.height = events.height 17 | array.width = events.width 18 | 19 | array.header.seq = seq 20 | array.header.stamp = _us_to_rostime(events.t[-1]) 21 | 22 | array.events = list(map(_event_to_event_msg, events.iter_events())) 23 | 24 | return array -------------------------------------------------------------------------------- /ev-licious/src/evlicious/tools/__init__.py: -------------------------------------------------------------------------------- 1 | from .utils import * 2 | from .task_manager import TaskManager 3 | from . import filters -------------------------------------------------------------------------------- /ev-licious/src/evlicious/tools/task_manager.py: -------------------------------------------------------------------------------- 1 | import multiprocessing as mp 2 | # from https://stackoverflow.com/questions/9601802/python-pool-apply-async-and-map-async-do-not-block-on-full-queue?rq=1 3 | from threading import Semaphore 4 | from multiprocessing import Pool 5 | import tqdm 6 | 7 | 8 | class TaskManager(object): 9 | def __init__(self, total, processes=4, queue_size=4, callback=None): 10 | self.pbar = tqdm.tqdm(total=total) 11 | self.pool = Pool(processes=processes) 12 | self.workers = Semaphore(processes + queue_size) 13 | self.callback = callback 14 | self.outputs = [] 15 | self.index = 0 16 | 17 | def __enter__(self): 18 | return self 19 | 20 | def __exit__(self, type, value, traceback): 21 | self.pool.close() 22 | self.pool.join() 23 | self.outputs = [(i, r.get()) for i, r in self.outputs] 24 | self.outputs = sorted(self.outputs, key=lambda x: x[0]) 25 | self.outputs = [o[1] for o in self.outputs] 26 | 27 | def new_task(self, function, *args, **kwargs): 28 | """Start a new task, blocks if queue is full.""" 29 | self.workers.acquire() 30 | res = self.pool.apply_async(function, args, kwargs, callback=self.task_done, 31 | error_callback=self.release_and_print) 32 | self.outputs += [(self.index, res)] 33 | self.index += 1 34 | 35 | def task_done(self, *args, **kwargs): 36 | """Called once task is done, releases the queue is blocked.""" 37 | self.workers.release() 38 | if self.callback is not None: 39 | self.callback(*args, **kwargs) 40 | self.pbar.update(1) 41 | 42 | def release_and_print(self, e): 43 | self.workers.release() 44 | print(e) -------------------------------------------------------------------------------- /ev-licious/tests/data/events.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/events.h5 -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000300.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000300.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000302.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000302.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000304.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000304.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000306.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000306.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000308.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000308.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000310.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000310.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000312.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000312.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000314.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000314.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000316.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000316.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000318.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000318.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000320.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000320.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000322.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000322.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000324.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000324.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000326.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000326.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000328.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000328.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000330.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000330.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000332.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000332.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000334.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000334.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000336.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000336.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000338.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000338.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000340.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000340.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000342.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000342.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000344.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000344.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000346.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000346.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000348.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000348.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000350.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000350.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000352.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000352.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000354.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000354.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000356.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000356.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000358.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000358.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000360.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000362.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000362.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000364.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000364.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000366.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000366.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000368.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000368.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000370.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000370.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000372.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000372.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000374.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000374.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000376.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000376.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000378.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000378.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000380.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000380.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000382.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000382.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000384.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000384.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000386.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000386.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000388.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000388.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000390.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000390.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000392.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000392.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000394.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000394.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000396.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000396.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000398.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000398.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000400.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000400.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000402.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000402.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000404.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000406.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000406.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000408.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000408.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000410.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000410.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000412.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000412.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000414.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000414.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000416.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000416.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000418.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000418.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000420.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000420.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000422.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000422.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000424.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000424.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000426.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000426.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000428.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000428.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000430.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000430.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000432.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000432.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000434.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000434.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000436.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000436.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000438.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000438.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000440.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000440.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000442.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000442.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000444.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000444.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000446.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000446.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000448.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000448.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000450.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000450.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000452.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000452.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000454.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000454.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000456.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000456.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000458.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000458.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000460.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000460.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000462.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000462.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000464.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000464.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000466.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000466.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000468.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000468.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000470.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000470.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000472.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000472.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000474.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000474.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000476.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000476.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000478.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000478.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000480.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000480.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000482.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000482.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000484.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000484.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000486.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000486.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000488.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000488.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000490.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000490.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000492.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000492.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000494.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000494.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000496.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000496.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/000498.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/ev-licious/tests/data/images/000498.jpg -------------------------------------------------------------------------------- /ev-licious/tests/data/images/timestamps.txt: -------------------------------------------------------------------------------- 1 | 4935099 2 | 4947610 3 | 4960119 4 | 4972629 5 | 4985139 6 | 4997649 7 | 5010159 8 | 5022669 9 | 5035178 10 | 5047688 11 | 5060198 12 | 5072707 13 | 5085217 14 | 5097727 15 | 5110236 16 | 5122746 17 | 5135256 18 | 5147766 19 | 5160275 20 | 5172785 21 | 5185295 22 | 5197805 23 | 5210315 24 | 5222824 25 | 5235334 26 | 5247843 27 | 5260354 28 | 5272863 29 | 5285373 30 | 5297882 31 | 5310392 32 | 5322902 33 | 5335412 34 | 5347921 35 | 5360431 36 | 5372941 37 | 5385450 38 | 5397960 39 | 5410471 40 | 5422980 41 | 5435490 42 | 5448000 43 | 5460509 44 | 5473019 45 | 5485528 46 | 5498038 47 | 5510548 48 | 5523058 49 | 5535568 50 | 5548077 51 | 5560587 52 | 5573097 53 | 5585606 54 | 5598116 55 | 5610626 56 | 5623136 57 | 5635646 58 | 5648156 59 | 5660665 60 | 5673175 61 | 5685684 62 | 5698194 63 | 5710704 64 | 5723214 65 | 5735723 66 | 5748233 67 | 5760742 68 | 5773253 69 | 5785762 70 | 5798272 71 | 5810782 72 | 5823292 73 | 5835801 74 | 5848311 75 | 5860821 76 | 5873330 77 | 5885840 78 | 5898350 79 | 5910859 80 | 5923370 81 | 5935879 82 | 5948388 83 | 5960899 84 | 5973409 85 | 5985917 86 | 5998428 87 | 6010937 88 | 6023447 89 | 6035957 90 | 6048467 91 | 6060977 92 | 6073486 93 | 6085996 94 | 6098506 95 | 6111015 96 | 6123525 97 | 6136035 98 | 6148544 99 | 6161054 100 | 6173564 101 | -------------------------------------------------------------------------------- /gryffin/.codecov.yml: -------------------------------------------------------------------------------- 1 | # For more configuration details: 2 | # https://docs.codecov.io/docs/codecov-yaml 3 | 4 | # Check if this file is valid by running in bash: 5 | # curl -X POST --data-binary @.codecov.yml https://codecov.io/validate 6 | 7 | # Coverage configuration 8 | # ---------------------- 9 | coverage: 10 | status: 11 | patch: false 12 | 13 | range: 70..90 # First number represents red, and second represents green 14 | # (default is 70..100) 15 | round: down # up, down, or nearest 16 | precision: 2 # Number of decimal places, between 0 and 5 17 | 18 | # Ignoring Paths 19 | # -------------- 20 | # which folders/files to ignore 21 | ignore: 22 | - tests 23 | - docs 24 | - setup.py 25 | - versioneer.py 26 | 27 | # Pull request comments: 28 | # ---------------------- 29 | # Diff is the Coverage Diff of the pull request. 30 | # Files are the files impacted by the pull request 31 | comment: 32 | layout: diff, files # accepted in any order: reach, diff, flags, and/or files -------------------------------------------------------------------------------- /gryffin/.github/workflows/continuous-integration.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies and run tests 2 | 3 | name: build 4 | 5 | on: 6 | push: 7 | branches: 8 | - master 9 | - feas 10 | - develop 11 | pull_request: 12 | branches: 13 | - master 14 | - feas 15 | - develop 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | strategy: 22 | matrix: 23 | os: [ubuntu-latest, macos-latest, windows-latest] 24 | python-version: [3.7, 3.8, 3.9] 25 | 26 | steps: 27 | - uses: actions/checkout@v2 28 | 29 | - name: Set up Python ${{ matrix.python-version }} 30 | uses: actions/setup-python@v2 31 | with: 32 | python-version: ${{ matrix.python-version }} 33 | 34 | - name: Install dependencies 35 | run: | 36 | pip install --upgrade pip setuptools wheel 37 | pip install --upgrade pytest 38 | pip install codecov 39 | pip install pytest 40 | pip install pytest-cov 41 | - name: Install package 42 | run: | 43 | pip install . 44 | 45 | - name: Test with pytest 46 | run: | 47 | pytest --cov=gryffin --cov-fail-under=5 --cov-report=xml 48 | - name: Upload coverage to Codecov 49 | uses: codecov/codecov-action@v1 50 | with: 51 | token: ${{ secrets.CODECOV_TOKEN }} 52 | file: ./coverage.xml 53 | flags: unittests 54 | fail_ci_if_error: false 55 | verbose: true 56 | -------------------------------------------------------------------------------- /gryffin/.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.9' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build --sdist 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /gryffin/.gitignore: -------------------------------------------------------------------------------- 1 | # files created by planners 2 | outcmaes/ 3 | *pyc 4 | *.swp 5 | 6 | ############ 7 | ### LOGS ### 8 | ############ 9 | *olympus*.pkl 10 | 11 | ################# 12 | ### DATABASES ### 13 | ################# 14 | *.db 15 | *scratch* 16 | 17 | # Byte-compiled / optimized / DLL files 18 | __pycache__/ 19 | *.py[cod] 20 | *$py.class 21 | 22 | # C extensions 23 | *.so 24 | 25 | # Distribution / packaging 26 | .Python 27 | build/ 28 | develop-eggs/ 29 | dist/ 30 | downloads/ 31 | eggs/ 32 | .eggs/ 33 | lib/ 34 | lib64/ 35 | parts/ 36 | sdist/ 37 | var/ 38 | wheels/ 39 | share/python-wheels/ 40 | *.egg-info/ 41 | .installed.cfg 42 | *.egg 43 | MANIFEST 44 | 45 | # PyInstaller 46 | # Usually these files are written by a python script from a template 47 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 48 | *.manifest 49 | *.spec 50 | 51 | # Installer logs 52 | pip-log.txt 53 | pip-delete-this-directory.txt 54 | 55 | # Unit test / coverage reports 56 | htmlcov/ 57 | .tox/ 58 | .nox/ 59 | .coverage 60 | .coverage.* 61 | .cache 62 | nosetests.xml 63 | coverage.xml 64 | *.cover 65 | *.py,cover 66 | .hypothesis/ 67 | .pytest_cache/ 68 | cover/ 69 | 70 | # Translations 71 | *.mo 72 | *.pot 73 | 74 | # Django stuff: 75 | *.log 76 | local_settings.py 77 | db.sqlite3 78 | db.sqlite3-journal 79 | 80 | # Flask stuff: 81 | instance/ 82 | .webassets-cache 83 | 84 | # Scrapy stuff: 85 | .scrapy 86 | 87 | # Sphinx documentation 88 | docs/_build/ 89 | 90 | # PyBuilder 91 | .pybuilder/ 92 | target/ 93 | 94 | # Jupyter Notebook 95 | .ipynb_checkpoints 96 | 97 | # IPython 98 | profile_default/ 99 | ipython_config.py 100 | 101 | # pyenv 102 | # For a library or package, you might want to ignore these files since the code is 103 | # intended to run in multiple environments; otherwise, check them in: 104 | # .python-version 105 | 106 | # pipenv 107 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 108 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 109 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 110 | # install all needed dependencies. 111 | #Pipfile.lock 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | # pytype static type analyzer 151 | .pytype/ 152 | 153 | # Cython debug symbols 154 | cython_debug/ 155 | 156 | # pycharm 157 | .idea/ 158 | -------------------------------------------------------------------------------- /gryffin/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-20.04 11 | tools: 12 | python: "3.9" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: docs/source/conf.py 17 | 18 | python: 19 | install: 20 | - method: pip 21 | path: . 22 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /gryffin/INSTALL.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/INSTALL.md -------------------------------------------------------------------------------- /gryffin/MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft src 2 | include README.md 3 | include LICENSE.md 4 | include versioneer.py 5 | include src/gryffin/_version.py 6 | include requirements.txt 7 | -------------------------------------------------------------------------------- /gryffin/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "parallel": "True", 4 | "boosted": "False" 5 | }, 6 | "parameters": [ 7 | {"name": "param_0", "type": "continuous", "low": 0.0, "high": 1.0, "size": 1}, 8 | {"name": "param_1", "type": "continuous", "low": 0.0, "high": 1.0, "size": 1}, 9 | {"name": "param_2", "type": "continuous", "low": 0.0, "high": 1.0, "size": 1}, 10 | {"name": "param_3", "type": "continuous", "low": 0.0, "high": 1.0, "size": 1}, 11 | {"name": "param_4", "type": "continuous", "low": 0.0, "high": 1.0, "size": 1} 12 | ], 13 | "objectives": [ 14 | {"name": "obj_0", "goal": "minimize"} 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /gryffin/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SPHINXPROJ = gryffin 9 | SOURCEDIR = source 10 | BUILDDIR = build 11 | 12 | # Put it first so that "make" without argument is like "make help". 13 | help: 14 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 15 | 16 | .PHONY: help Makefile 17 | 18 | # make documentation for github pages 19 | github: 20 | @make html 21 | @cp -a build/html/. ../docs 22 | 23 | # Catch-all target: route all unknown targets to Sphinx using the new 24 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 25 | %: Makefile 26 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 27 | -------------------------------------------------------------------------------- /gryffin/docs/README.rst: -------------------------------------------------------------------------------- 1 | Gryffin Documentation 2 | ===================== 3 | 4 | To build the documentation you will need to have the following packages installed: ``sphinx``, ``sphinx_rtd_theme``, 5 | ``msmb_theme``. You can install them all via ``pip``. You can also do this as follows:: 6 | 7 | pip install -r requirements.txt 8 | 9 | After this step you can generate the HTML documentation with:: 10 | 11 | make html 12 | 13 | You can then open the file ``build/html/index.html`` to read the docs. 14 | 15 | 16 | -------------------------------------------------------------------------------- /gryffin/docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /gryffin/docs/requirements.txt: -------------------------------------------------------------------------------- 1 | nbsphinx 2 | ipython 3 | sphinx-autodoc-typehints 4 | sphinx-rtd-theme 5 | -------------------------------------------------------------------------------- /gryffin/docs/source/_static/custom.css: -------------------------------------------------------------------------------- 1 | .wy-side-nav-search { 2 | background-color: #457B9D; 3 | } -------------------------------------------------------------------------------- /gryffin/docs/source/api_documentation.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ================== 3 | 4 | .. currentmodule:: gryffin 5 | 6 | Gryffin 7 | ------- 8 | .. autoclass:: Gryffin 9 | :members: 10 | 11 | .. automethod:: __init__ 12 | -------------------------------------------------------------------------------- /gryffin/docs/source/citation.rst: -------------------------------------------------------------------------------- 1 | Citation 2 | -------- 3 | 4 | If you use **Gryffin** in scientific publications, please cite the following papers depending on which aspects of the 5 | code you used. 6 | 7 | If you optimized **continuous variables**, please cite `this publication `_: 8 | 9 | :: 10 | 11 | @article{phoenics, 12 | title = {Phoenics: A Bayesian Optimizer for Chemistry}, 13 | author = {Florian Häse and Loïc M. Roch and Christoph Kreisbeck and Alán Aspuru-Guzik}, 14 | year = {2018} 15 | journal = {ACS Central Science}, 16 | number = {9}, 17 | volume = {4}, 18 | pages = {1134--1145} 19 | } 20 | 21 | 22 | If you optimized **categorical variables**, please cite `this publication `_: 23 | 24 | :: 25 | 26 | @article{gryffin, 27 | title = {Gryffin: An algorithm for Bayesian optimization of categorical variables informed by expert knowledge}, 28 | author = {Florian Häse and Matteo Aldeghi and Riley J. Hickman and Loïc M. Roch and Alán Aspuru-Guzik}, 29 | year = {2021}, 30 | journal = {Applied Physics Reviews}, 31 | number = {8}, 32 | pages = {031406} 33 | } 34 | 35 | If you performed a **multi-objective optimization**, or used **periodic variables**, please cite 36 | `this publication `_: 37 | 38 | :: 39 | 40 | @article{chimera, 41 | title = {Chimera: enabling hierarchy based multi-objective optimization for self-driving laboratories}, 42 | author = {Florian Häse and Loïc M. Roch and Alán Aspuru-Guzik}, 43 | year = {2018}, 44 | journal = {Chemical Science}, 45 | number = {9}, 46 | pages = {7642--7655} 47 | } 48 | 49 | If you performed an optimization with **known or unknown feasibility constraints**, or used ``genetic`` as the 50 | optimization algorithm for the acquisition, please cite `this publication `_: 51 | 52 | :: 53 | 54 | @article{gryffin_known_constraints, 55 | title={Bayesian optimization with known experimental and design constraints for chemistry applications}, 56 | author={Hickman, Riley J. and Aldeghi, Matteo and Häse, Florian and Aspuru-Guzik, Alán}, 57 | year={2022}, 58 | journal = {arXiv:2203.17241 [math.OC]}, 59 | } -------------------------------------------------------------------------------- /gryffin/docs/source/cli_documentation.rst: -------------------------------------------------------------------------------- 1 | Gryffin CLI 2 | ============ 3 | 4 | ``Gryffin`` also exposes a CLI interface that makes integrating the package into your workflow even more flexible. To run ``Gryffin`` from the command line simply run the command: 5 | 6 | .. code-block:: console 7 | 8 | $ gryffin -f FILE -c JSON 9 | 10 | 11 | There are two required argurments to run ``Gryffin`` from the command line. A filepath to an Excel or CSV file with all previous experiments must be provided and the usual ``Gryffin`` configuration file must be provided. Please refer to the Configuration section for the details of all configuration parameters. 12 | 13 | Required arguments: 14 | -f Excel/CSV file with all previous experiments. 15 | -c Json configuration file with parameters and objectives. 16 | 17 | The ``Gryffin`` CLI also exposes a number of optional argurments. For convenince, these arguments expose over-writable ``Gryffin`` configuration. 18 | 19 | Optional arguments: 20 | -h, --help show this help message and exit 21 | -n Number of experiments to suggest. Default is 1. Note that Gryffin will alternate between exploration and exploitation. 22 | --num_cpus Number of CPUs to use. Default is 1. 23 | --optimizer Algorithm to use to optimize the acquisition function. Choices are "adam" or "genetic". Default is "adam". 24 | --dynamic Whether to use dynamic Gryffin. Default is False. 25 | --feas_approach Approach to unknown feasibility constraints. Choices are: "fwa" (feasibility-weighted acquisition), "fca" (feasibility-constrained acquisition), "fia" (feasibility-interpolated 26 | acquisition). Default is "fia". 27 | --boosted Whether to use boosting. Default is False. 28 | --cached Whether to use caching. Default is False. 29 | --seed Random seed used for initialization. Default is 42. -------------------------------------------------------------------------------- /gryffin/docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | 16 | sys.path.insert(0, os.path.abspath("../../src")) 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = "Gryffin" 21 | copyright = "2021, The Matter Lab at the University of Toronto" 22 | author = "Matteo Aldeghi and Florian Häse" 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = "0.3.0" 26 | 27 | # -- General configuration --------------------------------------------------- 28 | 29 | master_doc = "index" 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named "sphinx.ext.*") or your custom 33 | # ones. 34 | extensions = [ 35 | "sphinx.ext.autodoc", 36 | "sphinx_autodoc_typehints", 37 | "sphinx.ext.autosummary", 38 | "sphinx_rtd_theme", 39 | "nbsphinx", 40 | "sphinx.ext.mathjax", 41 | "sphinx.ext.viewcode", 42 | ] 43 | autodoc_mock_imports = ["gryffin.bayesian_network"] 44 | 45 | # Add any paths that contain templates here, relative to this directory. 46 | templates_path = ["_templates"] 47 | 48 | # List of patterns, relative to source directory, that match files and 49 | # directories to ignore when looking for source files. 50 | # This pattern also affects html_static_path and html_extra_path. 51 | exclude_patterns = [] 52 | 53 | # -- Options for HTML output ------------------------------------------------- 54 | 55 | # The theme to use for HTML and HTML Help pages. See the documentation for 56 | # a list of builtin themes. 57 | # 58 | html_theme = "sphinx_rtd_theme" 59 | 60 | # Add any paths that contain custom static files (such as style sheets) here, 61 | # relative to this directory. They are copied after the builtin static files, 62 | # so a file named "default.css" will overwrite the builtin "default.css". 63 | html_static_path = [] 64 | -------------------------------------------------------------------------------- /gryffin/docs/source/getting_started.rst: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | Integrate Gryffin into your project quickly! 5 | 6 | 7 | Requirements 8 | ------------ 9 | 10 | * Python version >= 3.7 11 | 12 | 13 | Installation 14 | ------------ 15 | 16 | To install ``gryffin`` from `PyPI `_: 17 | 18 | .. code-block:: console 19 | 20 | $ pip install gryffin 21 | 22 | To install ``gryffin`` from source: 23 | 24 | .. code-block:: console 25 | 26 | $ git clone git@github.com:aspuru-guzik-group/gryffin.git 27 | $ cd gryffin 28 | $ pip install . 29 | 30 | Example Usage 31 | ------------- 32 | 33 | This is a minimalist example of Gryffin in action. 34 | 35 | 36 | .. code-block:: python 37 | 38 | from gryffin import Gryffin 39 | import experiment 40 | 41 | # load config 42 | config = { 43 | "parameters": [ 44 | {"name": "param_0", "type": "continuous", "low": 0.0, "high": 1.0}, 45 | ], 46 | objectives: [ 47 | {"name": "obj", "goal": "min"}, 48 | ] 49 | } 50 | 51 | # initialize gryffin 52 | gryffin = Gryffin( 53 | config_dict=config 54 | ) 55 | 56 | observations = [] 57 | for iter in range(ITER_BUDGET): 58 | 59 | # query gryffin for new params 60 | params = gryffin.recommend(observations=observations) 61 | 62 | # evaluate the proposed parameters 63 | merit = experiment.run(params) 64 | params['obj'] = merit 65 | 66 | observations.append(params) 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /gryffin/docs/source/tutorial.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | Explore this set of tutorials to get familiar with different Gryffin use cases. 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | 9 | tutorials/basic_usage 10 | tutorials/advanced_usage 11 | tutorials/perovskites 12 | 13 | -------------------------------------------------------------------------------- /gryffin/docs/source/tutorials/assets/advanced_usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/docs/source/tutorials/assets/advanced_usage.gif -------------------------------------------------------------------------------- /gryffin/docs/source/tutorials/assets/hoip_optimizer_performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/docs/source/tutorials/assets/hoip_optimizer_performance.png -------------------------------------------------------------------------------- /gryffin/docs/source/tutorials/assets/hoip_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/docs/source/tutorials/assets/hoip_space.png -------------------------------------------------------------------------------- /gryffin/docs/source/tutorials/perovskites.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/docs/source/tutorials/perovskites.pkl -------------------------------------------------------------------------------- /gryffin/docs/source/tutorials/robot.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/docs/source/tutorials/robot.rst -------------------------------------------------------------------------------- /gryffin/docs/source/tutorials/tf_params.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/docs/source/tutorials/tf_params.pickle -------------------------------------------------------------------------------- /gryffin/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["oldest-supported-numpy", "setuptools", "wheel", "cython"] 3 | 4 | -------------------------------------------------------------------------------- /gryffin/setup.cfg: -------------------------------------------------------------------------------- 1 | [versioneer] 2 | VCS = git 3 | style = pep440 4 | versionfile_source = src/gryffin/_version.py 5 | versionfile_build = gryffin/_version.py 6 | tag_prefix = '' 7 | parentdir_prefix = gryffin- 8 | -------------------------------------------------------------------------------- /gryffin/setup.py: -------------------------------------------------------------------------------- 1 | """Gryffin: An algorithm for Bayesian optimization of categorical variables informed by expert knowledge 2 | """ 3 | 4 | __author__ = "Florian Hase, Matteo Aldeghi" 5 | 6 | import versioneer 7 | from setuptools import setup, find_packages 8 | from distutils.extension import Extension 9 | import numpy as np 10 | 11 | 12 | # readme file 13 | def readme(): 14 | with open("README.md") as f: 15 | return f.read() 16 | 17 | 18 | # ---------- 19 | # Extensions 20 | # ---------- 21 | ext_modules = [ 22 | Extension( 23 | "gryffin.bayesian_network.kernel_evaluations", 24 | ["src/gryffin/bayesian_network/kernel_evaluations.c"], 25 | include_dirs=[np.get_include()], 26 | ), 27 | Extension( 28 | "gryffin.bayesian_network.kernel_prob_reshaping", 29 | ["src/gryffin/bayesian_network/kernel_prob_reshaping.c"], 30 | include_dirs=[np.get_include()], 31 | ), 32 | ] 33 | 34 | # ----- 35 | # Setup 36 | # ----- 37 | setup( 38 | name="gryffin", 39 | version=versioneer.get_version(), 40 | cmdclass=versioneer.get_cmdclass(), 41 | description="Bayesian optimization for continuous and categorical variables", 42 | long_description=readme(), 43 | long_description_content_type="text/markdown", 44 | classifiers=[ 45 | "Development Status :: 4 - Beta", 46 | "License :: OSI Approved :: Apache Software License", 47 | "Programming Language :: Python", 48 | "Intended Audience :: Science/Research", 49 | "Topic :: Scientific/Engineering", 50 | ], 51 | url="https://github.com/aspuru-guzik-group/gryffin", 52 | author="Florian Hase, Matteo Aldeghi", 53 | author_email="matteo.aldeghi@vectorinstitute.ai", 54 | license="Apache License 2.0", 55 | packages=find_packages("./src"), 56 | package_dir={"": "src"}, 57 | zip_safe=False, 58 | tests_require=["pytest"], 59 | install_requires=[ 60 | "numpy", 61 | "sqlalchemy", 62 | "rich", 63 | "pandas", 64 | "matter-chimera", 65 | "deap", 66 | "torch", 67 | "torchbnn", 68 | ], 69 | python_requires=">=3.7", 70 | ext_modules=ext_modules, 71 | entry_points={"console_scripts": ["gryffin = gryffin.cli:entry_point"]}, 72 | ) 73 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .gryffin import Gryffin 4 | from .utilities.defaults import get_config_defaults 5 | from .benchmark_functions import * 6 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/acquisition/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .acquisition import Acquisition 4 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/acquisition/genetic_optimizer/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | try: 4 | from deap import base 5 | except ImportError: 6 | print('package "deap" required by GeneticOptimizer not found, please install') 7 | 8 | from .genetic_optimizer import GeneticOptimizer 9 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/acquisition/gradient_optimizer/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .adam_optimizer import AdamOptimizer 4 | from .naive_categorical_optimizer import NaiveCategoricalOptimizer 5 | from .naive_discrete_optimizer import NaiveDiscreteOptimizer 6 | from .gradient_optimizer import GradientOptimizer 7 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/acquisition/gradient_optimizer/naive_categorical_optimizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | 6 | import numpy as np 7 | 8 | 9 | class NaiveCategoricalOptimizer: 10 | def __init__(self, func=None): 11 | self.func = func 12 | self.feature_sizes = None 13 | self.select_bool = None 14 | self.num_dims = None 15 | 16 | def set_func(self, func, select=None, feature_sizes=None): 17 | # set function 18 | self.func = func 19 | self.feature_sizes = feature_sizes 20 | if select is not None: 21 | self.select_bool = np.array(select) 22 | self.num_dims = len(self.select_bool) 23 | 24 | def get_update(self, vector): 25 | current_merit = self.func(vector) 26 | for i, select in enumerate(self.select_bool): 27 | if select is False: 28 | continue 29 | 30 | current_category = vector[i] 31 | new_category = np.random.choice(self.feature_sizes[i]) 32 | vector[i] = new_category 33 | 34 | new_merit = self.func(vector) 35 | 36 | # if new merit is better, keep change and update best merit... 37 | if new_merit < current_merit: 38 | current_merit = new_merit 39 | # else throw change away 40 | else: 41 | vector[i] = current_category 42 | return vector 43 | 44 | 45 | if __name__ == "__main__": 46 | import matplotlib.pyplot as plt 47 | import seaborn as sns 48 | 49 | colors = sns.color_palette("YlOrRd", 256) 50 | 51 | cat_opt = NaiveCategoricalOptimizer() 52 | highest = 20 53 | max_loss = np.sum(np.square(np.zeros(2) - highest / 2.0)) 54 | 55 | def func(array): 56 | loss = np.sum(np.square(array - highest / 2.0)) / max_loss 57 | return loss 58 | 59 | cat_opt.set_func(func, highest=[highest, highest], pos=np.arange(2)) 60 | 61 | lines = np.arange(highest + 2) - 0.5 62 | 63 | start = np.zeros(2) 64 | 65 | fig = plt.figure(figsize=(6, 6)) 66 | 67 | for _ in range(10**3): 68 | plt.clf() 69 | 70 | plt.plot(start[0], start[1], marker="o", color="k", markersize=10) 71 | 72 | for x_line in lines: 73 | plt.plot([lines[0], lines[-1]], [x_line, x_line], color="k", lw=0.5) 74 | plt.plot([x_line, x_line], [lines[0], lines[-1]], color="k", lw=0.5) 75 | 76 | for x_element in np.arange(highest + 1): 77 | for y_element in np.arange(highest + 1): 78 | array = np.array([x_element, y_element]) 79 | loss = func(array) 80 | color_index = int(255 * loss) 81 | plt.plot( 82 | x_element, 83 | y_element, 84 | color=colors[color_index], 85 | marker="s", 86 | markersize=10, 87 | alpha=0.5, 88 | ) 89 | 90 | start = cat_opt.get_update(start) 91 | 92 | plt.pause(0.05) 93 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/acquisition/gradient_optimizer/naive_discrete_optimizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | 6 | import numpy as np 7 | 8 | 9 | class NaiveDiscreteOptimizer: 10 | def __init__(self, func=None): 11 | self.func = func 12 | 13 | def _set_func(self, func, pos=None): 14 | self.func = func 15 | if pos is not None: 16 | self.pos = pos 17 | self.num_pos = len(pos) 18 | 19 | def set_func(self, func, pos=None, highest=None): 20 | self.highest = highest 21 | self._set_func(func, pos) 22 | 23 | def get_update(self, vector): 24 | func_best = self.func(vector) 25 | for pos_index, pos in enumerate(self.pos): 26 | if pos is None: 27 | continue 28 | 29 | current = vector[pos] 30 | perturb = np.random.choice(self.highest[pos_index]) 31 | vector[pos] = perturb 32 | 33 | func_cand = self.func(vector) 34 | if func_cand < func_best: 35 | func_best = func_cand 36 | else: 37 | vector[pos] = current 38 | return vector 39 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .category_reshaper import CategoryReshaper 4 | from .bayesian_network import BayesianNetwork 5 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/kernel_evaluations.pyxbld: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = 'Florian Hase' 4 | import numpy 5 | 6 | 7 | def make_ext(modname, pyxfilename): 8 | from distutils.extension import Extension 9 | ext = Extension(name=modname, 10 | sources=[pyxfilename]) 11 | return ext 12 | 13 | 14 | def make_setup_args(): 15 | return dict(script_args=['--verbose']) 16 | 17 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/kernel_evaluations.pyxbldc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/src/gryffin/bayesian_network/kernel_evaluations.pyxbldc -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/kernel_prob_reshaping.pyx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = 'Florian Hase' 4 | 5 | #======================================================================== 6 | 7 | import cython 8 | 9 | from cython.parallel import prange 10 | 11 | import numpy as np 12 | cimport numpy as np 13 | 14 | from libc.math cimport exp, sqrt 15 | 16 | #======================================================================== 17 | 18 | cdef class KernelReshaper: 19 | 20 | cdef int num_samples, num_obs, num_kernels, num_descriptors 21 | cdef np.ndarray np_recomputed_probs 22 | cdef np.ndarray np_all_distances 23 | 24 | def __init__(self): 25 | 26 | pass 27 | 28 | 29 | @cython.cdivision(True) 30 | @cython.boundscheck(False) 31 | cdef double [:, :, :] _reshape_probs(self, double [:, :, :] cat_probs, double [:, :] descriptors): 32 | 33 | cdef double [:, :, :] recomputed_probs = self.np_recomputed_probs 34 | cdef double [:, :, :] all_distances = self.np_all_distances 35 | 36 | cdef double ds2, dyi, sum_distances 37 | cdef double averaged_descriptor 38 | 39 | cdef int sample_index, obs_index, target_cat_index, desc_index, kernel_index 40 | 41 | for sample_index in prange(self.num_samples, nogil = True): 42 | 43 | for obs_index in range(self.num_obs): 44 | 45 | for desc_index in range(self.num_descriptors): 46 | 47 | averaged_descriptor = 0. 48 | for kernel_index in range(self.num_kernels): 49 | averaged_descriptor = cat_probs[sample_index, obs_index, kernel_index] * descriptors[kernel_index, desc_index] + averaged_descriptor 50 | 51 | 52 | for target_cat_index in range(self.num_kernels): 53 | 54 | ds2 = 0. 55 | for desc_index in range(self.num_descriptors): 56 | 57 | dyi = self.num_kernels * (descriptors[target_cat_index, desc_index] - averaged_descriptor) 58 | ds2 = ds2 + dyi * dyi 59 | 60 | all_distances[sample_index, obs_index, target_cat_index] = sqrt(ds2 / self.num_descriptors) 61 | 62 | # got all distances, compute probs from distances 63 | sum_distances = 0. 64 | for kernel_index in range(self.num_kernels): 65 | sum_distances = sum_distances + exp( - all_distances[sample_index, obs_index, kernel_index]) 66 | 67 | for kernel_index in range(self.num_kernels): 68 | recomputed_probs[sample_index, obs_index, kernel_index] = exp( - all_distances[sample_index, obs_index, kernel_index]) / sum_distances 69 | 70 | return recomputed_probs 71 | 72 | 73 | 74 | cpdef reshape_probs(self, np.ndarray cat_probs, np.ndarray descriptors): 75 | 76 | self.num_samples = cat_probs.shape[0] 77 | self.num_obs = cat_probs.shape[1] 78 | self.num_kernels = cat_probs.shape[2] 79 | self.num_descriptors = descriptors.shape[1] 80 | 81 | self.np_recomputed_probs = np.zeros((self.num_samples, self.num_obs, self.num_kernels)) 82 | self.np_all_distances = np.zeros((self.num_samples, self.num_obs, self.num_kernels)) 83 | 84 | cdef double [:, :, :] cat_probs_memview = cat_probs 85 | cdef double [:, :] descriptors_memview = descriptors 86 | 87 | reshaped_probs = self._reshape_probs(cat_probs_memview, descriptors_memview) 88 | return np.array(reshaped_probs) 89 | 90 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/kernel_prob_reshaping.pyxbld: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = 'Florian Hase' 4 | 5 | #======================================================================== 6 | 7 | def make_ext(modname, pyxfilename): 8 | from distutils.extension import Extension 9 | ext = Extension( 10 | name = modname, 11 | sources = [pyxfilename], 12 | ) 13 | return ext 14 | 15 | def make_setup_args(): 16 | return dict(script_args = ['--verbose']) 17 | 18 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/kernel_prob_reshaping.pyxbldc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/src/gryffin/bayesian_network/kernel_prob_reshaping.pyxbldc -------------------------------------------------------------------------------- /gryffin/src/gryffin/bayesian_network/torch_interface/__init__.py: -------------------------------------------------------------------------------- 1 | from .bnn import BNNTrainer 2 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/benchmark_functions/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .benchmark_functions_cont import ( 4 | dejong as dejong, 5 | hyper_ellipsoid as hyperellipsoid, 6 | rosenbrock_function as rosenbrock, 7 | rastrigin_function as rastrigin, 8 | schwefel_function as schwefel, 9 | ackley_path_function as ackley, 10 | linear_funnel, 11 | narrow_funnel, 12 | discrete_ackley, 13 | discrete_michalewicz, 14 | double_well, 15 | discrete_valleys, 16 | ) 17 | 18 | from .benchmark_functions_cat import ( 19 | Dejong as CatDejong, 20 | Ackley as CatAckley, 21 | Camel as CatCamel, 22 | Dejong as CatDejong, 23 | Michalewicz as CatMichalewicz, 24 | Slope as CatSlope, 25 | RandomCorrelated as CatRandomCorrelated, 26 | RandomUncorrelated as CatRandomUncorrelated, 27 | ) 28 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================== 6 | 7 | from .db_cache import DB_Cache 8 | from .db_werkzeug import DB_Werkzeug 9 | from .database_handler import DatabaseHandler 10 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/db_cache.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================== 6 | 7 | from gryffin.utilities import Logger 8 | 9 | # ======================================================================== 10 | 11 | 12 | class DB_Cache(Logger): 13 | def __init__(self, attributes, entries=[], verbosity=0): 14 | Logger.__init__(self, "DB_Cache", verbosity=verbosity) 15 | self.attributes = attributes 16 | 17 | self.cache = {attr: [] for attr in self.attributes} 18 | self.num_items = 0 19 | for entry in entries: 20 | self.add(entry) 21 | 22 | def __getitem__(self, item): 23 | try: 24 | return self.cache[item] 25 | except KeyError: 26 | return [] 27 | 28 | def add(self, info_dict): 29 | for attr in self.attributes: 30 | if attr in info_dict: 31 | self.cache[attr].append(info_dict[attr]) 32 | else: 33 | self.cache[attr].append(None) 34 | self.num_items += 1 35 | 36 | def fetch_all(self, condition_dict): 37 | results = [] 38 | for element_index in range(self.num_items): 39 | for key, value in condition_dict.items(): 40 | if value != self.cache[key][element_index]: 41 | break 42 | else: 43 | result = { 44 | attr: self.cache[attr][element_index] for attr in self.attributes 45 | } 46 | results.append(result) 47 | return results 48 | 49 | def update_all(self, condition_dict, update_dict): 50 | for element_index in range(self.num_items): 51 | for key, value in condition_dict.items(): 52 | if value != self.cache[key][element_index]: 53 | break 54 | else: 55 | for key, value in update_dict.items(): 56 | self.cache[key][element_index] = value 57 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/json_writers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | from DatabaseHandler.JsonWriters.db_writer import DB_Writer 8 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/pandas_writers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | import sys 8 | 9 | from utilities import PhoenicsModuleError 10 | 11 | # ======================================================================= 12 | 13 | try: 14 | import pandas 15 | except ModuleNotFoundError: 16 | _, error_message, _ = sys.exc_info() 17 | extension = "\n\tTry installing the pandas package of use a different database output format (e.g. pickle)." 18 | PhoenicsModuleError(str(error_message) + extension) 19 | 20 | try: 21 | import openpyxl 22 | except ModuleNotFoundError: 23 | _, error_message, _ = sys.exc_info() 24 | extension = "\n\tWriting to xlsx requires the openpyxl package. Please install the package or choose a different output format (e.g. csv or pickle)" 25 | PhoenicsModuleError(str(error_message) + extension) 26 | 27 | # ======================================================================= 28 | 29 | from DatabaseHandler.PandasWriters.db_writer import DB_Writer 30 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/pandas_writers/db_writer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from datetime import datetime 10 | 11 | from utilities import Logger 12 | 13 | # ======================================================================= 14 | 15 | 16 | class Writer(object): 17 | def __init__(self, file_name): 18 | self.file_name = file_name 19 | 20 | def save(self): 21 | pass 22 | 23 | 24 | class CsvWriter(Writer): 25 | def __init__(self, file_name): 26 | Writer.__init__(self, file_name) 27 | 28 | def __call__(self, pd_frame): 29 | pd_frame.to_csv(self.file_name) 30 | 31 | 32 | class ExcelWriter(Writer): 33 | def __init__(self, file_name): 34 | Writer.__init__(self, file_name) 35 | self.writer = pd.ExcelWriter(self.file_name) 36 | 37 | def __call__(self, pd_frame): 38 | pd_frame.to_excel(self.writer, "Sheet1") 39 | 40 | def save(self): 41 | self.writer.save() 42 | 43 | 44 | # ======================================================================= 45 | 46 | 47 | class DB_Writer(Logger): 48 | def __init__(self, config): 49 | self.config = config 50 | Logger.__init__(self, "DB_Writer", self.config.get("verbosity")) 51 | 52 | def create_writer(self, file_name, out_format): 53 | if out_format == "xlsx": 54 | self.writer = ExcelWriter(file_name) 55 | elif out_format == "csv": 56 | self.writer = CsvWriter(file_name) 57 | 58 | def write(self, db_content, outfile, out_format): 59 | # create the writer 60 | self.create_writer(outfile, out_format) 61 | 62 | # convert output dict and save via pandas routine 63 | dataframe = pd.DataFrame.from_dict(db_content) 64 | self.writer(dataframe) 65 | self.writer.save() 66 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/pickle_writers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | from DatabaseHandler.PickleWriters.db_writer import DB_Writer 8 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/pickle_writers/db_writer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | import pickle 8 | 9 | from utilities import Logger 10 | 11 | # ======================================================================= 12 | 13 | 14 | class DB_Writer(Logger): 15 | def __init__(self, config): 16 | self.config = config 17 | Logger.__init__(self, "DB_Writer", self.config.get("verbosity")) 18 | 19 | def write(self, db_content, outfile, out_format): 20 | pickle.dump(db_content, open(outfile, "wb")) 21 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/sqlite_interface/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | import sys 8 | 9 | from utilities import GryffinModuleError 10 | 11 | # ======================================================================= 12 | 13 | try: 14 | import sqlalchemy as sql 15 | except ModuleNotFoundError: 16 | _, error_message, _ = sys.exc_info() 17 | extension = "\n\tTry installing the sqlalchemy package or use a different database framework instead." 18 | GryffinModuleError(str(error_message) + extension) 19 | 20 | # ======================================================================= 21 | 22 | from .sqlite_operations import AddEntry, FetchEntries, UpdateEntries 23 | from .sqlite_database import SqliteDatabase 24 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/database_handler/sqlite_interface/sqlite_operations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================= 6 | 7 | import time 8 | import sqlalchemy as sql 9 | 10 | # ======================================================================= 11 | 12 | 13 | class AddEntry(object): 14 | def __init__(self, database, table, entry): 15 | self.db = database 16 | self.table = table 17 | self.entry = entry 18 | 19 | def execute(self): 20 | with self.db.connect() as conn: 21 | conn.execute(self.table.insert(), self.entry) 22 | conn.close() 23 | 24 | 25 | # ======================================================================= 26 | 27 | 28 | class FetchEntries(object): 29 | def __init__(self, database, table, selection): 30 | self.db = database 31 | self.table = table 32 | self.selection = selection 33 | self.entries = None 34 | self.executed = False 35 | self.entries_fetched = False 36 | 37 | def execute(self): 38 | with self.db.connect() as conn: 39 | selected = conn.execute(self.selection) 40 | entries = selected.fetchall() 41 | conn.close() 42 | self.entries = entries 43 | self.executed = True 44 | 45 | def get_entries(self): 46 | iteration_index = 0 47 | while not self.executed: 48 | time.sleep(0.02) 49 | self.entries_fetched = True 50 | return self.entries 51 | 52 | 53 | # ======================================================================= 54 | 55 | 56 | class UpdateEntries(object): 57 | def __init__(self, database, table, updates): 58 | self.db = database 59 | self.table = table 60 | self.updates = updates 61 | 62 | def execute(self): 63 | with self.db.connect() as conn: 64 | updated = conn.execute(self.updates) 65 | conn.close() 66 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/descriptor_generator/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env 2 | 3 | __author__ = "Florian Hase" 4 | 5 | import sys 6 | from gryffin.utilities import GryffinModuleError 7 | 8 | from .descriptor_generator import DescriptorGenerator 9 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/observation_processor/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from .observation_processor import ObservationProcessor 3 | from .observation_processor import param_dict_to_vector, param_vector_to_dict 4 | from .observation_processor import param_dicts_to_vectors, param_vectors_to_dicts 5 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/random_sampler/__init__.py: -------------------------------------------------------------------------------- 1 | from .random_sampler import RandomSampler 2 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/sample_selector/__init__.py: -------------------------------------------------------------------------------- 1 | from .sample_selector import SampleSelector 2 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .decorators import safe_execute 4 | from .defaults import default_general_configuration 5 | from .defaults import default_database_configuration 6 | from .defaults import default_model_configuration 7 | 8 | from .exceptions import GryffinParseError 9 | from .exceptions import GryffinModuleError 10 | from .exceptions import GryffinNotFoundError 11 | from .exceptions import GryffinUnknownSettingsError 12 | from .exceptions import GryffinValueError 13 | from .exceptions import GryffinVersionError 14 | from .exceptions import GryffinComputeError 15 | from .exceptions import GryffinSettingsError 16 | 17 | from .logger import Logger 18 | 19 | from .json_parser import ParserJSON 20 | from .pickle_parser import ParserPickle 21 | from .category_parser import CategoryParser 22 | from .config_parser import ConfigParser 23 | 24 | from .infos import parse_time, memory_usage, print_memory_usage 25 | 26 | from .constraint_utils import estimate_feas_fraction, compute_constrained_cartesian 27 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase" 4 | 5 | import sys 6 | import traceback 7 | 8 | 9 | class AbstractError(Exception): 10 | def __init__(self, message): 11 | self.__call__(message) 12 | 13 | def __call__(self, message): 14 | error_traceback = traceback.format_exc() 15 | error_traceback = "\n".join(error_traceback.split("\n")[:-2]) + "\n\n" 16 | error_type = "\x1b[0;31m%s: %s\x1b[0m\n" % (self.name, message) 17 | 18 | if "SystemExit" in error_traceback: 19 | return None 20 | 21 | sys.stderr.write(error_traceback) 22 | sys.stderr.write(error_type) 23 | sys.exit() 24 | 25 | 26 | class GryffinModuleError(AbstractError): 27 | name = "GryffinModuleError" 28 | 29 | 30 | class GryffinNotFoundError(AbstractError): 31 | name = "GryffinNotFoundError" 32 | 33 | 34 | class GryffinParseError(AbstractError): 35 | name = "GryffinParseError" 36 | 37 | 38 | class GryffinSettingsError(AbstractError): 39 | name = "GryffinSettingsError" 40 | 41 | 42 | class GryffinUnknownSettingsError(AbstractError): 43 | name = "GryffinUnknownSettingsError" 44 | 45 | 46 | class GryffinValueError(AbstractError): 47 | name = "GryffinValueError" 48 | 49 | 50 | class GryffinVersionError(AbstractError): 51 | name = "GryffinVersionError" 52 | 53 | 54 | class GryffinComputeError(AbstractError): 55 | name = "GryffinComputeError" 56 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/infos.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import resource 4 | import sys 5 | 6 | 7 | def parse_time(start, end): 8 | elapsed = end - start # elapsed time in seconds 9 | if elapsed <= 1.0: 10 | ms = elapsed * 1000.0 11 | time_string = f"{ms:.1f} ms" 12 | elif 1.0 < elapsed < 60.0: 13 | time_string = f"{elapsed:.1f} s" 14 | else: 15 | m, s = divmod(elapsed, 60) 16 | time_string = f"{m:.0f} min {s:.0f} s" 17 | return time_string 18 | 19 | 20 | def memory_usage(): 21 | if sys.platform == "darwin": # MacOS --> memory in bytes 22 | kB = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss // 1000.0 23 | else: # Linux --> memory in kilobytes 24 | kB = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 25 | 26 | GB = kB // 1000000.0 27 | MB = kB // 1000.0 28 | kB = kB % 1000.0 29 | return GB, MB, kB 30 | 31 | 32 | def print_memory_usage(): 33 | GB, MB, kB = memory_usage() 34 | print(f"==> MEMORY USAGE: {GB:.0f} GB, {MB:.0f} MB, {kB:.0f} kB") 35 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/json_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================== 6 | 7 | import json 8 | 9 | # ======================================================================== 10 | 11 | 12 | class ParserJSON(object): 13 | def __init__(self, json_file=None): 14 | self.json_file = json_file 15 | 16 | def parse(self, json_file=None): 17 | # update json file 18 | if not json_file is None: 19 | self.json_file = json_file 20 | 21 | # parse configuration 22 | if not self.json_file is None: 23 | with open(self.json_file) as content: 24 | self.parsed_json = json.loads(content.read()) 25 | else: 26 | from utilities.defaults import default_configuration 27 | 28 | self.parsed_json = default_configuration 29 | return self.parsed_json 30 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/logger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Florian Hase, Matteo Aldeghi" 4 | 5 | import sys 6 | import traceback 7 | from rich.console import Console 8 | 9 | 10 | class Logger: 11 | # DEBUG, INFO --> stdout 12 | # WARNING, ERROR, FATAL --> stderr 13 | 14 | VERBOSITY_LEVELS = { 15 | 0: ["FATAL"], 16 | 1: ["FATAL", "ERROR"], 17 | 2: ["FATAL", "ERROR", "WARNING"], 18 | 3: ["FATAL", "ERROR", "WARNING", "STATS"], # minimal info 19 | 4: ["FATAL", "ERROR", "WARNING", "STATS", "INFO"], # richer info 20 | 5: ["FATAL", "ERROR", "WARNING", "STATS", "INFO", "DEBUG"], 21 | } 22 | 23 | WRITER = { 24 | "DEBUG": sys.stdout, 25 | "INFO": sys.stdout, 26 | "WARNING": sys.stderr, 27 | "ERROR": sys.stderr, 28 | "FATAL": sys.stderr, 29 | } 30 | 31 | # more colors and styles: 32 | # https://stackoverflow.com/questions/2048509/how-to-echo-with-different-colors-in-the-windows-command-line 33 | # https://joshtronic.com/2013/09/02/how-to-use-colors-in-command-line-output/ 34 | 35 | NONE = "" 36 | WHITE = "#ffffff" 37 | GREEN = "#d9ed92" 38 | GRAY = "#d3d3d3" 39 | YELLOW = "#f9dc5c" 40 | ORANGE = "#f4a261" 41 | RED = "#e5383b" 42 | PURPLE = "#9d4edd" 43 | 44 | COLORS = { 45 | "DEBUG": GRAY, 46 | "INFO": NONE, 47 | "STATS": NONE, 48 | "WARNING": ORANGE, 49 | "ERROR": RED, 50 | "FATAL": PURPLE, 51 | } 52 | 53 | def __init__(self, name, verbosity=4): 54 | """ 55 | name : str 56 | name to give this logger. 57 | verbosity : int 58 | verbosity level, between ``0`` and ``4``. with ``0`` only ``FATAL`` messages are shown, with ``1`` also 59 | ``ERROR``, with ``2`` also ``WARNING``, with ``3`` also ``INFO``, with ``4`` also ``DEBUG``. Default 60 | is ``3``. 61 | """ 62 | self.name = name 63 | self.verbosity = verbosity 64 | self.verbosity_levels = self.VERBOSITY_LEVELS[self.verbosity] 65 | self.console = Console(stderr=False) 66 | self.error_console = Console(stderr=True) 67 | 68 | def update_verbosity(self, verbosity=3): 69 | self.verbosity = verbosity 70 | self.verbosity_levels = self.VERBOSITY_LEVELS[self.verbosity] 71 | 72 | def log(self, message, message_type): 73 | # check if we need to log the message 74 | if message_type in self.verbosity_levels: 75 | color = self.COLORS[message_type] 76 | error_message = None 77 | if message_type in ["WARNING", "ERROR", "FATAL"]: 78 | error_message = traceback.format_exc() 79 | if "NoneType: None" not in error_message: 80 | self.error_console.print(error_message, style=f"{color}") 81 | 82 | self.console.print(message, style=f"{color}") 83 | return error_message, message 84 | 85 | def log_chapter(self, title, line="─", style="#34a0a4"): 86 | if self.verbosity >= 4: 87 | title = " " + title + " " 88 | self.console.print(f"{title:{line}^80}", style=style) 89 | -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/params.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/gryffin/src/gryffin/utilities/params.pkl -------------------------------------------------------------------------------- /gryffin/src/gryffin/utilities/pickle_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env 2 | 3 | __author__ = "Florian Hase" 4 | 5 | # ======================================================================== 6 | 7 | import pickle 8 | 9 | # ======================================================================== 10 | 11 | 12 | class ParserPickle(object): 13 | def __init__(self, pickle_file=None): 14 | self.pickle_file = pickle_file 15 | 16 | def parse(self, pickle_file=None): 17 | # update pickle file 18 | if not pickle_file is None: 19 | self.pickle_file = pickle_file 20 | 21 | # parse configuration 22 | if not self.pickle_file is None: 23 | with open(self.pickle_file, "rb") as content: 24 | self.parsed_pickle = pickle.load(content) 25 | return self.parsed_pickle 26 | -------------------------------------------------------------------------------- /gryffin/tests/test_gryffin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from gryffin import Gryffin 3 | import shutil 4 | import numpy as np 5 | 6 | 7 | def test_recommend(): 8 | config = { 9 | "general": { 10 | "save_database": False, 11 | "num_cpus": 1, 12 | "boosted": True, 13 | "sampling_strategies": 2, 14 | "random_seed": 42, 15 | }, 16 | "parameters": [ 17 | {"name": "param_0", "type": "continuous", "low": 0, "high": 1}, 18 | {"name": "param_1", "type": "continuous", "low": 0, "high": 1}, 19 | ], 20 | "objectives": [{"name": "obj", "goal": "min"}], 21 | } 22 | 23 | observations = [ 24 | {"param_0": 0.3, "param_1": 0.4, "obj": 0.1}, 25 | {"param_0": 0.5, "param_1": 0.6, "obj": 0.2}, 26 | ] 27 | 28 | gryffin = Gryffin(config_dict=config) 29 | _ = gryffin.recommend(observations=observations) 30 | 31 | 32 | def test_multiobjective(): 33 | config = { 34 | "general": { 35 | "save_database": False, 36 | "num_cpus": 1, 37 | "boosted": True, 38 | "sampling_strategies": 2, 39 | "random_seed": 42, 40 | }, 41 | "parameters": [ 42 | {"name": "param_0", "type": "continuous", "low": 0, "high": 1}, 43 | {"name": "param_1", "type": "continuous", "low": 0, "high": 1}, 44 | ], 45 | "objectives": [ 46 | {"name": "obj0", "goal": "min", "tolerance": 0.2, "absolute": False}, 47 | {"name": "obj1", "goal": "max", "tolerance": 0.1, "absolute": False}, 48 | ], 49 | } 50 | 51 | observations = [ 52 | {"param_0": 0.3, "param_1": 0.4, "obj0": 0.1, "obj1": 0.2}, 53 | {"param_0": 0.5, "param_1": 0.6, "obj0": 0.2, "obj1": 0.1}, 54 | ] 55 | 56 | gryffin = Gryffin(config_dict=config) 57 | _ = gryffin.recommend(observations=observations) 58 | -------------------------------------------------------------------------------- /gryffin/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py{37}-{tfprob} 3 | skipsdist = True 4 | 5 | [testenv] 6 | deps = 7 | numpy 8 | pytest 9 | pytest-cov>=2.8.1 10 | pytest-randomly 11 | 12 | commands = 13 | pip install -r requirements.txt 14 | 15 | [testenv:py37-tfprob] 16 | commands = 17 | pip install -r requirements.txt 18 | pip install -e . 19 | pytest --cov=gryffin --cov-append --cov-report=xml tests/ 20 | -------------------------------------------------------------------------------- /n_imagenet/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /n_imagenet/base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/n_imagenet/base/__init__.py -------------------------------------------------------------------------------- /n_imagenet/base/data/data_container.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from math import ceil 3 | 4 | 5 | class DataContainer(ABC): 6 | """ 7 | Abstract class defining data container. 8 | A typical data container will encompass all the utilities related to dataset generation and loading. 9 | Note that cfg contains all the neccessary data needed to create a dataset. 10 | """ 11 | 12 | def __init__(self, cfg, **kwargs): 13 | super(DataContainer, self).__init__() 14 | self.cfg = cfg 15 | # dataset is a dict containing different torch.utils.data.Dataset instances 16 | self.dataset = {"train": None, "test": None, "val": None} 17 | # dataloader is a dict containing different torch.utils.data.DataLoader instances 18 | self.dataloader = {"train": None, "test": None, "val": None} 19 | 20 | @abstractmethod 21 | def gen_dataset(self, **kwargs): 22 | """ 23 | Method for generating dataset. Sets the key-value pairs in self.dataset. 24 | """ 25 | pass 26 | 27 | @abstractmethod 28 | def gen_dataloader(self, **kwargs): 29 | """ 30 | Method for creating dataloader. Sets the key-value pairs in self.dataloader. 31 | It is highly recommended to write a custom collate_fn, to pass around data as a dictionary. 32 | This enables efficient code recycling. 33 | """ 34 | assert self.dataset is not None 35 | 36 | 37 | class DataChunkContainer(DataContainer): 38 | """ 39 | Abstract class defining data chunk container. Data will be pre-loaded into RAM for faster data loading. 40 | For DataChunkContainer to successfully work, the Dataset generated from gen_dataset should be an instance of ChunkDataset. 41 | """ 42 | 43 | def __init__(self, cfg, **kwargs): 44 | super(DataChunkContainer, self).__init__(cfg) 45 | self.chunk_every = ceil(self.cfg.chunk_size / self.cfg.batch_size) 46 | 47 | def create_chunk(self, batch_idx, mode): 48 | """ 49 | Load chunk to RAM. 50 | """ 51 | if batch_idx % self.chunk_every == 0: 52 | print(f"Creating chunk with index {self.dataset[mode].chunk_idx}") 53 | self.dataset[mode].load_chunk() 54 | 55 | def refresh_chunk(self, mode): 56 | """ 57 | Free chunk, and prepare for new epoch. 58 | """ 59 | print("Refreshing chunk!") 60 | self.dataset[mode].restart_chunk() 61 | self.dataset[mode].free_chunk() 62 | self.dataset[mode].shuffle_index() 63 | 64 | def release_chunk(self, mode): 65 | """ 66 | Free chunk to save RAM. 67 | """ 68 | print("Releasing chunk!") 69 | self.dataset[mode].free_chunk() 70 | -------------------------------------------------------------------------------- /n_imagenet/base/data/dataset.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset 2 | 3 | 4 | class ChunkDataset(Dataset): 5 | """ 6 | Class implementing chunk-based loading. 7 | """ 8 | 9 | def __init__(self, cfg, mode="train"): 10 | super(ChunkDataset, self).__init__() 11 | self.cfg = cfg 12 | self.mode = mode 13 | self.chunk_idx = 0 # Next chunk index to load 14 | 15 | def shuffle_index(self): 16 | """ 17 | Shuffle indices for re-sampling chunk. 18 | """ 19 | raise NotImplementedError 20 | 21 | def load_chunk(self): 22 | """ 23 | Load a chunk to RAM. 24 | """ 25 | raise NotImplementedError 26 | 27 | def restart_chunk(self): 28 | self.chunk_idx = 0 29 | 30 | def free_chunk(self): 31 | """ 32 | Free all reserved chunks to save RAM space. 33 | """ 34 | raise NotImplementedError 35 | -------------------------------------------------------------------------------- /n_imagenet/base/train/metrics.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | def accuracy(output, target, topk=(1,)): 5 | """Computes the accuracy over the k top predictions for the specified values of k""" 6 | with torch.no_grad(): 7 | maxk = max(topk) 8 | batch_size = target.size(0) 9 | 10 | _, pred = output.topk(maxk, 1, True, True) 11 | pred = pred.t() 12 | correct = pred.eq(target.reshape(1, -1).expand_as(pred)) 13 | 14 | res = [] 15 | for k in topk: 16 | correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True) 17 | res.append(correct_k.mul_(1.0 / (batch_size)).item()) 18 | return res 19 | -------------------------------------------------------------------------------- /n_imagenet/base/utils/parse_utils.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | import configparser 3 | from ast import literal_eval 4 | from pathlib import Path 5 | 6 | NO_PARSE = ["name", "load_model"] # List of names to avoid parsing 7 | EXCEPT_NONE = ["load_model"] 8 | 9 | 10 | def parse_ini(config_path: str): 11 | read_config = configparser.ConfigParser() 12 | config_name = Path(config_path).stem 13 | 14 | read_config.read(config_path) 15 | config_attribs = [] 16 | data_dict = {} 17 | 18 | for section in read_config.sections(): 19 | for key, value in read_config.items(section): 20 | config_attribs.append(key) 21 | data_dict[key] = parse_value(value) if key not in NO_PARSE else value 22 | if key in EXCEPT_NONE and value == "None": # Account for None 23 | data_dict[key] = None 24 | 25 | # Modify name just in case of errors 26 | data_dict["name"] = config_name 27 | 28 | Config = namedtuple("Config", config_attribs) 29 | cfg = Config(**data_dict) 30 | return cfg 31 | 32 | 33 | def parse_value(value): 34 | if ( 35 | value.replace(".", "", 1) 36 | .replace("+", "", 1) 37 | .replace("-", "", 1) 38 | .replace("e", "", 1) 39 | .isdigit() 40 | ): 41 | # Exponential format and decimal format should be accounted for 42 | return literal_eval(value) 43 | elif value == "True" or value == "False": 44 | if value == "True": 45 | return True 46 | else: 47 | return False 48 | elif value == "None": 49 | return None 50 | elif "," in value: # Config contains lists 51 | is_number = any(char.isdigit() for char in value.split(",")[0]) 52 | items_list = value.split(",") 53 | 54 | if "" in items_list: 55 | items_list.remove("") 56 | if is_number: 57 | return [literal_eval(val) for val in items_list] 58 | else: 59 | if '"' in items_list[0] and "'" in items_list[0]: 60 | return [literal_eval(val.strip()) for val in items_list] 61 | else: 62 | return [val.strip() for val in items_list] 63 | else: 64 | return value 65 | -------------------------------------------------------------------------------- /n_imagenet/base/utils/time_utils.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class TimerError(Exception): 5 | """A custom exception used to report errors in use of Timer class""" 6 | 7 | 8 | class Timer: 9 | def __init__(self, verbose=False): 10 | self._start_time = None 11 | self.verbose = verbose 12 | 13 | def start(self): 14 | """Start a new timer""" 15 | if self._start_time is not None: 16 | raise TimerError("Timer is running. Use .stop() to stop it") 17 | 18 | self._start_time = time.perf_counter() 19 | 20 | def stop(self, new_msg=None): 21 | """Stop the timer, and report the elapsed time""" 22 | if self._start_time is None: 23 | raise TimerError("Timer is not running. Use .start() to start it") 24 | 25 | elapsed_time = time.perf_counter() - self._start_time 26 | self._start_time = None 27 | if self.verbose: 28 | if new_msg is not None: 29 | print(f"Elapsed time: {elapsed_time:0.4f} seconds " + new_msg) 30 | else: 31 | print(f"Elapsed time: {elapsed_time:0.4f} seconds") 32 | return elapsed_time 33 | else: 34 | return elapsed_time 35 | 36 | 37 | def time_proto(msg): 38 | def time_func(func): 39 | def time_wrapper(*args, **kwargs): 40 | t = Timer() 41 | t.start() 42 | return_val = func(*args, **kwargs) 43 | t.stop(msg) 44 | return return_val 45 | 46 | return time_wrapper 47 | 48 | return time_func 49 | -------------------------------------------------------------------------------- /n_imagenet/environment.yml: -------------------------------------------------------------------------------- 1 | name: e2t 2 | channels: 3 | - pytorch 4 | - defaults 5 | - conda-forge 6 | dependencies: 7 | - pip 8 | - python=3.7 9 | - pytorch 10 | - torchvision 11 | - cudatoolkit=10.1 12 | - opencv 13 | - tqdm 14 | - scikit-video 15 | - eigen 16 | - boost 17 | - boost-cpp 18 | - pybind11 19 | - nltk 20 | - flake8 21 | - tensorboard 22 | - scikit-image 23 | - matplotlib 24 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/.gitignore: -------------------------------------------------------------------------------- 1 | Datasets/ 2 | logs/ 3 | experiments/ 4 | *_local.sh 5 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/n_imagenet/real_cnn_model/__init__.py -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_four_channel_big_kernel_random_idx.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=./Datasets/Imagenet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=256 11 | seed=1 12 | parallel=True 13 | model=ResNet34 14 | channel_size=4 15 | kernel_size=14 16 | num_classes=1000 17 | [DataLoader] 18 | train_file=./Datasets/N_Imagenet/train_list.txt 19 | val_file=./Datasets/N_Imagenet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=None 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_acc_count 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | [Debug] 52 | debug=False 53 | debug_input=True 54 | inspect_channel=all 55 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_four_channel_big_kernel_random_idx_mini.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=/data/scratch1/nzubic/datasets/Mini_N_ImageNet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=64 11 | seed=1 12 | parallel=False 13 | model=ResNet34 14 | channel_size=12 15 | kernel_size=14 16 | num_classes=100 17 | [DataLoader] 18 | train_file=/data/scratch1/nzubic/datasets/Mini_N_ImageNet/train_list.txt 19 | val_file=/data/scratch1/nzubic/datasets/Mini_N_ImageNet/train_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=100 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_acc_count 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | [Debug] 52 | debug=False 53 | debug_input=True 54 | inspect_channel=all 55 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_one_channel_big_kernel_random_idx.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=./Datasets/Imagenet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=256 11 | seed=1 12 | parallel=True 13 | model=ResNet34 14 | channel_size=1 15 | kernel_size=14 16 | num_classes=1000 17 | [DataLoader] 18 | train_file=./Datasets/N_Imagenet/train_list.txt 19 | val_file=./Datasets/N_Imagenet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=None 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_flat 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | [Debug] 52 | debug=False 53 | debug_input=True 54 | inspect_channel=all 55 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_one_channel_big_kernel_random_idx_mini.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=./Datasets/Imagenet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=64 11 | seed=1 12 | parallel=False 13 | model=ResNet34 14 | channel_size=1 15 | kernel_size=14 16 | num_classes=100 17 | [DataLoader] 18 | train_file=./Datasets/N_Imagenet/train_list.txt 19 | val_file=./Datasets/N_Imagenet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=100 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_flat 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | [Debug] 52 | debug=False 53 | debug_input=True 54 | inspect_channel=all 55 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_sort_big_kernel_random_idx.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=./Datasets/Imagenet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=256 11 | seed=1 12 | parallel=True 13 | model=ResNet34 14 | channel_size=2 15 | kernel_size=14 16 | num_classes=1000 17 | [DataLoader] 18 | train_file=./Datasets/N_Imagenet/train_list.txt 19 | val_file=./Datasets/N_Imagenet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=None 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_acc_sort 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | [Sort] 52 | global_time=False 53 | neglect_polarity=False 54 | strict=True 55 | denoise_sort=False 56 | denoise_image=False 57 | filter_flash=False 58 | filter_noise=False 59 | use_image=False 60 | quantize_sort=None 61 | [Debug] 62 | debug=False 63 | debug_input=True 64 | inspect_channel=all 65 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_two_channel_big_kernel_random_idx.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=./Datasets/Imagenet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=256 11 | seed=1 12 | parallel=True 13 | model=ResNet34 14 | channel_size=2 15 | kernel_size=14 16 | num_classes=1000 17 | [DataLoader] 18 | train_file=./Datasets/N_Imagenet/train_list.txt 19 | val_file=./Datasets/N_Imagenet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=None 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_flat_pol 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | noise_inject=True 52 | [Debug] 53 | debug=False 54 | debug_input=True 55 | inspect_channel=all 56 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_acc_two_channel_big_kernel_random_idx_mini.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=/data/scratch1/nzubic/datasets/Mini_N_ImageNet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=64 11 | seed=1 12 | parallel=False 13 | model=ResNet34 14 | channel_size=2 15 | kernel_size=14 16 | num_classes=100 17 | [DataLoader] 18 | train_file=/data/scratch1/nzubic/datasets/Mini_N_ImageNet/train_list.txt 19 | val_file=/data/scratch1/nzubic/datasets/Mini_N_ImageNet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=epoch 26 | quantized=True 27 | trim_class_count=100 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_flat_pol 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | noise_inject=True 52 | [Debug] 53 | debug=False 54 | debug_input=True 55 | inspect_channel=all 56 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | name=this_is_gonna_rock 3 | mode=train 4 | height=224 5 | width=224 6 | load_model=None 7 | save_root_dir=./experiments/ 8 | label_map=/shares/rpg.ifi.uzh/nzubic/datasets/Mini_N_ImageNet/ILSVRC2012_devkit_t12/data/mapping.txt 9 | no_cuda=False 10 | batch_size=64 11 | seed=1 12 | parallel=False 13 | model=ResNet34 14 | channel_size=12 15 | kernel_size=14 16 | num_classes=100 17 | [DataLoader] 18 | train_file=/shares/rpg.ifi.uzh/nzubic/datasets/Mini_N_ImageNet/train_list.txt 19 | val_file=/shares/rpg.ifi.uzh/nzubic/datasets/Mini_N_ImageNet/val_list.txt 20 | augment=True 21 | augment_type=base_augment 22 | on_the_fly=False 23 | pin_memory=True 24 | num_workers=6 25 | save_by=best 26 | quantized=True 27 | trim_class_count=100 28 | [Preprocessing] 29 | reshape=True 30 | reshape_method=no_sample 31 | interpolate=None 32 | loader_type=reshape_then_acc_count 33 | [Slice] 34 | slice_events=True 35 | slice_length=30000 36 | slice_method=random 37 | slice_augment=False 38 | slice_augment_width=0 39 | slice_start=0 40 | slice_end=30000 41 | [Train] 42 | optimizer=Adam 43 | epochs=100 44 | save_every=1 45 | learning_rate=0.0003 46 | momentum=0.9 47 | weight_decay=1e-4 48 | temperature=1 49 | max_trajectory_speed=0.0 50 | mahalanobis=0.0 51 | [Debug] 52 | debug=False 53 | debug_input=True 54 | inspect_channel=all 55 | -------------------------------------------------------------------------------- /n_imagenet/real_cnn_model/data/.gitignore: -------------------------------------------------------------------------------- 1 | *.pt 2 | *_local.py 3 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_event_histogram.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source activate event_representation 4 | 5 | python n_imagenet/real_cnn_model/main.py --config "n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini" --override 'loader_type=reshape_then_tore' 6 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_event_histogram.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #SBATCH --cpus-per-task=8 3 | #SBATCH --mem=96G 4 | #SBATCH --time=72:00:00 5 | #SBATCH --gres=gpu:1 # The GPU model is optional, you can simply specify 'gpu:1' 6 | #SBATCH --output=final_outputs/mininimagenet_event_histogram.txt 7 | 8 | module load gpu cuda anaconda3 9 | srun mininimagenet_event_histogram.bash 10 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_event_stack.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source activate event_representation 4 | 5 | python n_imagenet/real_cnn_model/main.py --config "n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini" --override 'loader_type=reshape_then_event_stack' 6 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_event_stack.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #SBATCH --cpus-per-task=8 3 | #SBATCH --mem=96G 4 | #SBATCH --time=72:00:00 5 | #SBATCH --gres=gpu:1 # The GPU model is optional, you can simply specify 'gpu:1' 6 | #SBATCH --output=final_outputs/mininimagenet_event_stack.txt 7 | 8 | module load gpu cuda anaconda3 9 | srun mininimagenet_event_stack.bash 10 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_optimized.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source activate event_representation 4 | 5 | python n_imagenet/real_cnn_model/main.py --config "n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini" --override 'loader_type=reshape_then_optimized' 6 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_optimized.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #SBATCH --cpus-per-task=8 3 | #SBATCH --mem=96G 4 | #SBATCH --time=72:00:00 5 | #SBATCH --gres=gpu:1 # The GPU model is optional, you can simply specify 'gpu:1' 6 | #SBATCH --output=final_outputs/mininimagenet_optimized.txt 7 | 8 | module load gpu cuda anaconda3 9 | srun mininimagenet_optimized.bash 10 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_time_surface.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source activate event_representation 4 | 5 | python n_imagenet/real_cnn_model/main.py --config "n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini" --override 'loader_type=reshape_then_time_surface' 6 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_time_surface.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #SBATCH --cpus-per-task=8 3 | #SBATCH --mem=96G 4 | #SBATCH --time=72:00:00 5 | #SBATCH --gres=gpu:1 # The GPU model is optional, you can simply specify 'gpu:1' 6 | #SBATCH --output=final_outputs/mininimagenet_time_surface.txt 7 | 8 | module load gpu cuda anaconda3 9 | srun mininimagenet_time_surface.bash 10 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_tore.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source activate event_representation 4 | 5 | python n_imagenet/real_cnn_model/main.py --config "n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini" --override 'loader_type=reshape_then_tore' 6 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_tore.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #SBATCH --cpus-per-task=8 3 | #SBATCH --mem=96G 4 | #SBATCH --time=72:00:00 5 | #SBATCH --gres=gpu:1 # The GPU model is optional, you can simply specify 'gpu:1' 6 | #SBATCH --output=final_outputs/mininimagenet_tore.txt 7 | 8 | module load gpu cuda anaconda3 9 | srun mininimagenet_tore.bash 10 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_voxel_grid.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source activate event_representation 4 | 5 | python n_imagenet/real_cnn_model/main.py --config "n_imagenet/real_cnn_model/configs/imagenet/cnn_adam_twelve_channel_big_kernel_random_idx_mini.ini" --override 'loader_type=reshape_then_voxel_grid' 6 | -------------------------------------------------------------------------------- /n_imagenet/scripts/mininimagenet_voxel_grid.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #SBATCH --cpus-per-task=8 3 | #SBATCH --mem=96G 4 | #SBATCH --time=72:00:00 5 | #SBATCH --gres=gpu:1 # The GPU model is optional, you can simply specify 'gpu:1' 6 | #SBATCH --output=final_outputs/mininimagenet_voxel_grid.txt 7 | 8 | module load gpu cuda anaconda3 9 | srun mininimagenet_voxel_grid.bash 10 | -------------------------------------------------------------------------------- /representations/gen4_transforms.py: -------------------------------------------------------------------------------- 1 | # author: Nikola Zubic 2 | 3 | from representations.event_stack import EventStack 4 | import tonic.transforms as tonic_transforms 5 | from representations.time_surface import ToTimesurface 6 | import numpy as np 7 | import numpy.lib.recfunctions as rfn 8 | from representations.optimized_representation import get_optimized_representation 9 | from representations.tore import events2ToreFeature 10 | 11 | 12 | def get_item_transform( 13 | reshaped_return_data, representation_name, transform, height, width, num_events 14 | ): 15 | if "ToVoxelGrid" in representation_name: 16 | transformation = transform((width, height, 2), n_time_bins=12) 17 | rep = transformation(reshaped_return_data) 18 | rep = rep.transpose(0, 2, 3, 1)[..., 0] 19 | rep = rep.transpose(1, 2, 0) * 255 20 | 21 | elif "MixedDensityEventStack" in representation_name: 22 | rep = get_optimized_representation( 23 | reshaped_return_data, num_events, height, width 24 | ) 25 | rep *= 255 26 | 27 | elif "EventStack" in representation_name: 28 | reshaped_return_data["p"] = (reshaped_return_data["p"] + 1) // 2 29 | stack_size = 12 30 | transformation = EventStack(stack_size, num_events, height, width) 31 | pre_stack = transformation.pre_stack( 32 | reshaped_return_data, reshaped_return_data[-1]["t"] 33 | ) 34 | post_stack = transformation.post_stack(pre_stack) 35 | rep = post_stack.transpose(0, 1, 3, 2)[..., 0] * 255 36 | # rep = post_stack.reshape(height, width, stack_size) * 255 37 | 38 | elif "ToImage" in representation_name: 39 | transformation = transform((width, height, 2)) 40 | reshaped_return_data["p"] = (reshaped_return_data["p"] + 1) // 2 41 | rep = transformation(reshaped_return_data) 42 | rep = rep.transpose(1, 2, 0) 43 | rep *= 255 44 | 45 | elif "TORE" in representation_name.upper(): 46 | k = 6 47 | x, y, ts, pol = ( 48 | reshaped_return_data["x"], 49 | reshaped_return_data["y"], 50 | reshaped_return_data["t"], 51 | reshaped_return_data["p"], 52 | ) 53 | 54 | # Normalize the data for TORE representation conversion 55 | x = x - min(x) + 1 56 | y = y - min(y) + 1 57 | sampleTimes = ts[-1] 58 | frameSize = (max(y), max(x)) 59 | 60 | rep = events2ToreFeature(x, y, ts, pol, sampleTimes, k, frameSize) 61 | rep *= 255 62 | 63 | elif "ToTimesurface" in representation_name: 64 | reshaped_return_data["p"] = ((reshaped_return_data["p"] + 1) / 2).astype( 65 | np.int8 66 | ) 67 | transform = ToTimesurface( 68 | sensor_size=(width, height, 2), 69 | surface_dimensions=None, 70 | tau=50000, 71 | decay="exp", 72 | ) 73 | t = reshaped_return_data["t"] 74 | t_norm = (t - t[0]) / (t[-1] - t[0]) * 6 75 | idx = np.searchsorted(t_norm, np.arange(6) + 1) 76 | 77 | rep = transform(reshaped_return_data, idx) 78 | rep = rep.reshape((-1, rep.shape[-2], rep.shape[-1])) 79 | rep = rep.transpose(1, 2, 0) 80 | 81 | rep *= 255 82 | 83 | return rep 84 | -------------------------------------------------------------------------------- /representations/representation_search/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/representations/representation_search/__init__.py -------------------------------------------------------------------------------- /representations/representation_search/chosen_indexes.py: -------------------------------------------------------------------------------- 1 | # Subset of GEN1 dataset indexes that are chosen to be used for optimization. 2 | chosen = [ 3 | 860, 4 | 993, 5 | 1025, 6 | 1037, 7 | 1103, 8 | 1446, 9 | 1487, 10 | 1769, 11 | 2193, 12 | 2216, 13 | 2244, 14 | 2854, 15 | 2961, 16 | 3032, 17 | 3112, 18 | 3233, 19 | 3677, 20 | 3949, 21 | 3959, 22 | 4332, 23 | 4567, 24 | 4893, 25 | 4911, 26 | 5042, 27 | 5053, 28 | 5419, 29 | 5671, 30 | 5887, 31 | 6187, 32 | 6918, 33 | 7232, 34 | 7938, 35 | 8240, 36 | 8245, 37 | 8571, 38 | 8741, 39 | 9096, 40 | 9520, 41 | 9613, 42 | 9632, 43 | 9772, 44 | 10131, 45 | 10142, 46 | 10175, 47 | 10413, 48 | 10425, 49 | 10561, 50 | 10983, 51 | 11477, 52 | 11622, 53 | 11658, 54 | 12049, 55 | 12075, 56 | 12077, 57 | 12166, 58 | 12272, 59 | 12334, 60 | 12568, 61 | 12680, 62 | 12771, 63 | 12897, 64 | 13002, 65 | 13263, 66 | 13390, 67 | 14108, 68 | 14183, 69 | 14650, 70 | 14717, 71 | 15025, 72 | 15099, 73 | 15120, 74 | 15161, 75 | 15696, 76 | 15905, 77 | 15916, 78 | 16109, 79 | 16357, 80 | 16526, 81 | 16874, 82 | 16994, 83 | 17014, 84 | 17395, 85 | 17705, 86 | 17791, 87 | 17909, 88 | 18366, 89 | 18529, 90 | 18588, 91 | 18657, 92 | 18823, 93 | 18942, 94 | 19374, 95 | 19409, 96 | 19565, 97 | 19604, 98 | 19648, 99 | 20138, 100 | 20148, 101 | 20241, 102 | 20249, 103 | ] 104 | 105 | # enough to converge to a good solution 106 | chosen_voxel_grid = [28, 29, 30, 31, 32, 34, 37, 38, 98, 99] 107 | chosen_event_histogram = [17, 18, 52, 53, 57, 60, 63, 67, 68, 71, 75, 82, 99] 108 | chosen_time_surface = [13] 109 | chosen_event_stack = [ 110 | 4, 111 | 7, 112 | 13, 113 | 20, 114 | 25, 115 | 32, 116 | 40, 117 | 44, 118 | 47, 119 | 50, 120 | 52, 121 | 55, 122 | 56, 123 | 58, 124 | 59, 125 | 66, 126 | 75, 127 | 78, 128 | 79, 129 | 80, 130 | 83, 131 | 84, 132 | 92, 133 | 98, 134 | ] 135 | chosen_optimized_representation = [4, 8, 11, 13, 33, 35, 37, 65, 76, 89] 136 | 137 | event_representations = { 138 | "VoxelGrid": chosen_voxel_grid, 139 | "EventHistogram": chosen_event_histogram, 140 | "TimeSurface": chosen_time_surface, 141 | "EventStack": chosen_event_stack, 142 | "OptimizedRepresentation": chosen_optimized_representation, 143 | "TORE": [i for i in range(100)], 144 | } 145 | 146 | 147 | def extract_indexes(event_representation_name): 148 | # event_representation_name 149 | target_list = event_representations[event_representation_name] 150 | 151 | return [chosen[pos] for pos in target_list if pos < len(chosen)] 152 | -------------------------------------------------------------------------------- /representations/time_surface.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import Union, Tuple 3 | import numpy as np 4 | import numba 5 | 6 | 7 | @dataclass(frozen=True) 8 | class ToTimesurface: 9 | """Create global or local time surfaces for each event. Modeled after the paper Lagorce et al. 10 | 2016, Hots: a hierarchy of event-based time-surfaces for pattern recognition 11 | https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=7508476. 12 | Parameters: 13 | sensor_size: a 3-tuple of x,y,p for sensor_size 14 | surface_dimensions (int, int): width does not have to be equal to height, however both numbers have to be odd. 15 | if surface_dimensions is None: the time surface is defined globally, on the whole sensor grid. 16 | tau (float): time constant to decay events around occuring event with. 17 | decay (str): can be either 'lin' or 'exp', corresponding to linear or exponential decay. 18 | """ 19 | 20 | sensor_size: Tuple[int, int, int] 21 | surface_dimensions: Union[None, Tuple[int, int]] = None 22 | tau: float = 5e3 23 | decay: str = "lin" 24 | 25 | def __call__(self, events, indices): 26 | timestamp_memory = np.zeros( 27 | (self.sensor_size[2], self.sensor_size[1], self.sensor_size[0]) 28 | ) 29 | timestamp_memory -= self.tau * 3 + 1 30 | all_surfaces = np.zeros( 31 | ( 32 | len(indices), 33 | self.sensor_size[2], 34 | self.sensor_size[1], 35 | self.sensor_size[0], 36 | ) 37 | ) 38 | 39 | to_timesurface_numpy( 40 | events["x"], 41 | events["y"], 42 | events["t"], 43 | events["p"], 44 | indices, 45 | timestamp_memory, 46 | all_surfaces, 47 | tau=self.tau, 48 | ) 49 | return all_surfaces 50 | 51 | 52 | @numba.jit(nopython=True) 53 | def to_timesurface_numpy(x, y, t, p, indices, timestamp_memory, all_surfaces, tau=5e3): 54 | """Representation that creates timesurfaces for each event in the recording. Modeled after the 55 | paper Lagorce et al. 2016, Hots: a hierarchy of event-based time-surfaces for pattern 56 | recognition https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=7508476. 57 | Parameters: 58 | surface_dimensions (int, int): width does not have to be equal to height, however both numbers have to be odd. 59 | if surface_dimensions is None: the time surface is defined globally, on the whole sensor grid. 60 | tau (float): time constant to decay events around occuring event with. 61 | decay (str): can be either 'lin' or 'exp', corresponding to linear or exponential decay. 62 | Returns: 63 | array of timesurfaces with dimensions (w,h) or (p,w,h) 64 | """ 65 | current_index_pos = 0 66 | for index in range(len(x)): 67 | timestamp_memory[p[index], y[index], x[index]] = t[index] 68 | 69 | if index == indices[current_index_pos]: 70 | timestamp_context = timestamp_memory - t[index] 71 | all_surfaces[current_index_pos, :, :, :] = np.exp(timestamp_context / tau) 72 | current_index_pos += 1 73 | if current_index_pos > len(indices) - 1: 74 | break 75 | -------------------------------------------------------------------------------- /viz/2_map_gwd_correlation.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | 3 | plt.rcParams["text.usetex"] = True 4 | plt.rcParams["font.size"] = "16" 5 | plt.rcParams["lines.linewidth"] = 1 6 | 7 | 8 | def plot(C_p, methods, mAP, colors, labels, xlim, ylim, dataset_name="Gen1"): 9 | fig, ax = plt.subplots(figsize=(10, 5)) 10 | 11 | for i, key in enumerate(methods): 12 | ax.scatter(mAP[i], C_p, c=colors[i], label=key) 13 | 14 | ax.set_ylabel("GWD [-]") 15 | ax.set_xlabel(f"mAP [-]") 16 | 17 | ax.legend( 18 | frameon=True, 19 | loc="lower left", 20 | handletextpad=0.1, 21 | borderpad=0.2, 22 | borderaxespad=0.5, 23 | fontsize=14, 24 | ) 25 | 26 | ax.annotate( 27 | text=rf"\textbf{{{dataset_name}}}", 28 | fontsize=21, 29 | xy=(xlim[1] - 0.03, ylim[1] - 0.03), 30 | ) 31 | 32 | ax.set_ylim(ylim) 33 | ax.set_xlim(xlim) 34 | 35 | for idx, label in enumerate(labels): 36 | ax.annotate(text=label, fontsize=14, xy=(mAP[0][idx] + 0.02, C_p[idx] - 0.005)) 37 | 38 | return fig, ax 39 | 40 | 41 | # gen1 42 | markers = ["*", "^", "s"] 43 | colors = ["r", "g", "b"] 44 | methods = ["Swin-V2", "EfficientRep", "ResNet-50"] 45 | labels = ["EST", "Voxel Grid", "MDES", "Time Surface", "2D Histogram", "TORE"] 46 | 47 | C_p = [ 48 | 0.3552, 49 | 0.40281647785577745, 50 | 0.38314795761716137, 51 | 0.3252, 52 | 0.621960598186318, 53 | 0.3694, 54 | ] 55 | mAP = [ 56 | [0.4531, 0.4249, 0.4375, 0.5007, 0.3598, 0.4465], 57 | [0.41, 0.3812, 0.3933, 0.4233, 0.3189, 0.4001], 58 | [0.37, 0.3398, 0.3445, 0.3765, 0.2781, 0.3589], 59 | ] 60 | 61 | # fig, ax = plot(C_p, methods, mAP, colors, labels, xlim=[0.25, 0.55], ylim=[0.28, 0.65], dataset_name="Gen1") 62 | 63 | # uncomment this one only if you want to plot without our method 64 | fig, ax = plot( 65 | C_p, 66 | methods, 67 | mAP, 68 | colors, 69 | labels, 70 | xlim=[0.25, 0.55], 71 | ylim=[0.28, 0.65], 72 | dataset_name="Gen1", 73 | ) 74 | 75 | 76 | # plot our method 77 | C_p_ours = 0.30449148912568236 78 | ax.scatter(0.519, C_p_ours, c="r", marker="*", s=200) 79 | ax.annotate( 80 | text=r"\textbf{ERGO-12 (ours)}", fontsize=14, xy=(0.519 - 0.07, C_p_ours + 0.02) 81 | ) 82 | # fig.savefig("/home/nzubic/map_vs_cp_gen1.pdf", bbox_inches="tight") 83 | 84 | 85 | # gen4 86 | C_p = [ 87 | 0.4091, 88 | 0.43281647785577745, 89 | 0.40314795761716137, 90 | 0.4271, 91 | 0.661960598186318, 92 | 0.4129, 93 | ] 94 | mAP = [ 95 | [0.3870, 0.38078, 0.38813, 0.3832, 0.32945, 0.3864], 96 | [0.3705, 0.36511, 0.37234, 0.3672, 0.31235, 0.3691], 97 | [0.3478, 0.33983, 0.35010, 0.3421, 0.23181, 0.3458], 98 | ] 99 | 100 | labels = ["EST", "Voxel Grid", "Time Surface", "MDES", "2D Histogram", "TORE"] 101 | 102 | fig, ax = plot( 103 | C_p, 104 | methods, 105 | mAP, 106 | colors, 107 | labels, 108 | xlim=[0.20, 0.45], 109 | ylim=[0.39, 0.7], 110 | dataset_name="1 Mpx", 111 | ) 112 | # fig.savefig("/home/nzubic/map_vs_cp_gen4.pdf", bbox_inches="tight") 113 | 114 | plt.show() 115 | -------------------------------------------------------------------------------- /viz/4_toy_examples.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | plt.rcParams["text.usetex"] = True 5 | plt.rcParams["font.size"] = "16" 6 | plt.rcParams["lines.linewidth"] = 1 7 | 8 | 9 | # MDES, VoxelGrid together - on x-axis we have number of bins, on y-axis GWD metric on full GEN1 validation dataset 10 | fig, ax = plt.subplots(figsize=(10, 3)) 11 | A = ax.plot( 12 | [1, 2, 3, 9, 12, 15], 13 | [ 14 | 0.74673848532958439, 15 | 0.68001254864549601, 16 | 0.57114556320014550, 17 | 0.42159948575664453, 18 | 0.40281647785577745, 19 | 0.36334685743319348, 20 | ], 21 | marker=".", 22 | c="red", 23 | label="Voxel Grid", 24 | ) 25 | B = ax.plot( 26 | [1, 2, 3, 9, 12, 15], 27 | [ 28 | 0.74507481102355310, 29 | 0.66752351335679215, 30 | 0.55550015758080901, 31 | 0.39159504580790515, 32 | 0.38314795761716137, 33 | 0.33123495847331357, 34 | ], 35 | marker=".", 36 | c="blue", 37 | label="MDES", 38 | ) 39 | ax.set_xlabel("Number of channels") 40 | ax.set_ylabel("GWD") 41 | ax.legend( 42 | frameon=True, 43 | loc="lower left", 44 | framealpha=1, 45 | edgecolor="0", 46 | handletextpad=0.1, 47 | borderpad=0.2, 48 | borderaxespad=0.5, 49 | fontsize=14, 50 | ) 51 | ax.set_xticks(np.arange(1, 16)) 52 | ax.set_xticklabels(np.arange(1, 16)) 53 | fig.savefig(bbox_inches="tight", fname="/home/nzubic/toy_example_num_channels.pdf") 54 | 55 | 56 | # VG and MDES where on x-axis we have number of sigma kernel blur operations applied on 12 channels and on y-axis we have GWD 57 | fig, ax = plt.subplots(figsize=(10, 3)) 58 | ax.plot( 59 | [0, 2, 4], 60 | [0.40281647785577745, 0.67015056789313240, 0.80191055608035412], 61 | marker=".", 62 | c="red", 63 | label="Voxel Grid", 64 | ) 65 | ax.plot( 66 | [0, 2, 4], 67 | [0.38314795761716136, 0.6304820476545163, 0.782242035841738], 68 | marker=".", 69 | c="blue", 70 | label="MDES", 71 | ) 72 | ax.set_ylim([0.17, 0.82]) 73 | 74 | ax.set_xlabel("Gaussian blur $\sigma$ [pix]") 75 | ax.set_ylabel("GWD") 76 | ax.legend( 77 | frameon=True, 78 | loc="lower left", 79 | framealpha=1, 80 | edgecolor="0", 81 | handletextpad=0.1, 82 | borderpad=0.2, 83 | borderaxespad=0.5, 84 | fontsize=14, 85 | ) 86 | 87 | ax.set_xticks([0, 2, 4]) 88 | ax.set_xticklabels([0, 2, 4]) 89 | fig.savefig(bbox_inches="tight", fname="/home/nzubic/toy_example_blur_radius.pdf") 90 | 91 | plt.show() 92 | -------------------------------------------------------------------------------- /viz/5_appendix_plots.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | 3 | plt.rcParams["text.usetex"] = True 4 | plt.rcParams["font.size"] = "16" 5 | plt.rcParams["lines.linewidth"] = 1 6 | 7 | 8 | def plot(C_p, methods, mAP, colors, labels, xlim, ylim, dataset_name="Gen1"): 9 | fig, ax = plt.subplots(figsize=(10, 5)) 10 | 11 | for i, key in enumerate(methods): 12 | ax.scatter(mAP[i], C_p, c=colors[i], label=key) 13 | 14 | ax.set_ylabel(r"GWD$_{100}$ [-]") 15 | ax.set_xlabel(f"mAP [-]") 16 | 17 | ax.legend( 18 | frameon=True, 19 | loc="lower left", 20 | handletextpad=0.1, 21 | borderpad=0.2, 22 | borderaxespad=0.5, 23 | fontsize=14, 24 | ) 25 | 26 | ax.annotate( 27 | text=rf"\textbf{{{dataset_name}}}", 28 | fontsize=21, 29 | xy=(xlim[1] - 0.03, ylim[1] - 0.03), 30 | ) 31 | 32 | ax.set_ylim(ylim) 33 | ax.set_xlim(xlim) 34 | 35 | for idx, label in enumerate(labels): 36 | if label.startswith("ERGO"): 37 | ax.annotate( 38 | text=rf"\textbf{{{label}}}", fontsize=14, xy=(mAP[0][idx], C_p[idx]) 39 | ) 40 | ax.scatter(mAP[0][idx], C_p[idx], c="r", marker="*", s=200) 41 | else: 42 | ax.annotate(text=label, fontsize=14, xy=(mAP[0][idx], C_p[idx])) 43 | 44 | return fig, ax 45 | 46 | 47 | # gen1 48 | markers = ["*", "^", "s"] 49 | colors = ["r", "g", "b"] 50 | methods = ["Swin-V2"] 51 | labels = ["Voxel Grid", "MDES", "Time Surface", "TORE", "ERGO-12", "ERGO-9", "ERGO-7"] 52 | 53 | C_p = [ 54 | 0.517637696535689, 55 | 0.497969176297073, 56 | 0.4725212186799115, 57 | 0.4842212186799116, 58 | 0.46558974599468906, 59 | 0.49039721437555236, 60 | 0.50803210774350944, 61 | ] 62 | mAP = [[0.4249, 0.4375, 0.5007, 0.4465, 0.519, 0.4400, 0.4300]] 63 | 64 | # fig, ax = plot(C_p, methods, mAP, colors, labels, xlim=[0.25, 0.55], ylim=[0.28, 0.65], dataset_name="Gen1") 65 | 66 | # uncomment this one only if you want to plot without our method 67 | fig, ax = plot( 68 | C_p, 69 | methods, 70 | mAP, 71 | colors, 72 | labels, 73 | xlim=[0.42, 0.54], 74 | ylim=[0.46, 0.525], 75 | dataset_name="Gen1", 76 | ) 77 | fig.savefig("/home/nzubic/gen_one_channels_supp.pdf", bbox_inches="tight") 78 | 79 | # gen4 80 | C_p = [ 81 | 0.517637696535689, 82 | 0.4725212186799115, 83 | 0.497969176297073, 84 | 0.4842212186799116, 85 | 0.46558974599468906, 86 | 0.49039721437555236, 87 | 0.50803210774350944, 88 | ] 89 | mAP = [[0.38078, 0.38813, 0.3832, 0.3864, 0.419, 0.3850, 0.3815]] 90 | 91 | labels = ["Voxel Grid", "Time Surface", "MDES", "TORE", "ERGO-12", "ERGO-9", "ERGO-7"] 92 | 93 | fig, ax = plot( 94 | C_p, 95 | methods, 96 | mAP, 97 | colors, 98 | labels, 99 | xlim=[0.38, 0.425], 100 | ylim=[0.46, 0.525], 101 | dataset_name="1 Mpx", 102 | ) 103 | fig.savefig("/home/nzubic/one_mpx_channels_supp.pdf", bbox_inches="tight") 104 | 105 | plt.show() 106 | -------------------------------------------------------------------------------- /viz/ergo12_visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uzh-rpg/event_representation_study/27b939aa39366e05677d0ce087fac82448e7de44/viz/ergo12_visualization.png --------------------------------------------------------------------------------