Code Monkey home page Code Monkey logo

kmap's Introduction

kMap.py

kMap.py is a python based program for simulation and data analysis in photoemission tomography. The underlying theoretical methodology is described in the following publication:

Dominik Brandstetter, Xiaosheng Yang, Daniel Lüftner, F. Stefan Tautz, and Peter Puschnig, "kMap.py: A Python program for simulation and data analysis in photoemission tomography", Computer Physics Communications, available online (2021) https://doi.org/10.1016/j.cpc.2021.107905

Please cite this work when using results from kMap.py in your publications.

It provides an easy-to-use graphical user interface powered by PyQt5 to simulate photoemission momentum maps of molecular orbitals and to perform a one-to-one comparison between simulation and experiment. For this kMap.py provides tools like line- or region-restricted intensity scans/plots, interpolation capabilities, adjustable simulation parameters (like orientation, final state kinetic energy and polarization state of the incident light field) as well as an interface to powerful least-square fits between simulation and experiment to quickly determine optimal parameters.

GitHub Page: https://github.com/brands-d/kMap

Authors

Quick-Start

Installation:

pip install kMap

Usage:

python -m kmap

Pre-packaged distribution (Windows 10 only)

A built distribution for an old kMap verison is available on request for Windows 10 in form of a .zip file. For this, please send an email to peter.puschnig(at)uni-graz.at. To use this version of kMap, please unzuip the file, enter the resulting folder and double click the kMap.exe file.

Detailed installation guide from source

The installation is mostly done via make commands. Because Windows does not support Makefiles natively, this installation guide will differ between Linux and Windows at multiple points. Please follow the part corresponding to your operating system. For Mac users: As MacOS natively support bash, the Linux guide should work fine.

1. Install Python

Before installing kMap.py, please make sure you have a python version of 3.8 or higher installed. If not, you can get one here

https://www.python.org/downloads/

With this, you should have pip already installed. If not please install it using this guide (https://pip.pypa.io/en/stable/installing/).

Note: If you are using Python 3.7 you might need to install importlib_metadata manually using: pip install importlib_metadata

2. Clone Git Project

Clone the project into a local repository. If you have git installed, simply execute the following command for https:

git clone https://github.com/brands-d/kMap.git

or if you have an ssh connection set up:

git clone [email protected]:brands-d/kMap.git

Alternatively, if don't have git installed you can download the .zip file here:

https://github.com/brands-d/kMap/archive/master.zip

and extract the project into the local directory.

3. Virtual environment

It is recommended to use a virtual environment to run kMap.py in. If you are using Anaconda or are familiar with venv, please set up a new environment and activate it. Then skip ahead to section 5. Installation. If you don't want to utilize a virtual environment at all, please also skip ahead to section 5. Installation.

To use a virtual environment please check if you have virtualenv already installed. If not please do so with the following command:

pip install virtualenv

Linux

The following commands will set up a virtual environment inside the kMap's root directory

make setup

Windows

Please execute the following commands. If your shell does not recognize the "rm" command, replace "rm" with "del".

rm -rf venv build dist *.egg-info
python -m venv venv

4. Activate Enviroment

The environment is set up but needs to be activated manually. ATTENTION: You will need to reactivate the environment for every new shell again. Please follow this point to do so.

Linux

source ./venv/bin/activate

Windows

.\venv\Scripts\activate

To deactivate the environment simply call (both operation systems)

deactivate

5. Installation

If you skipped section 3. and 4. please make sure you are in the environment you want the packages to be installed in. Additionally, please make sure you are using the latest version of pip as PyQt5 is known to have trouble with older versions. You can (should) upgrade pip using

pip install --upgrade pip

If you want to have more control over what is happening, please follow the "Manually" section.

The following commands will install kMap.py and all necessary packages inside

Linux

make install

Windows

python setup.py install

5. Testing

Last please run the tests to check if they come back passing.

Linux

make test-all

Windows

python -m unittest discover

It should say something like "OK" at the end. If you see "FAILED" one or more tests came back negative. If that's the case please make sure you installed kMap.py correctly and retry. If it still fails, please contact one of the authors.

Configuration

All configuration files can be found in ./kmap/config. Each configuration file (logging, settings and shortcut) exists in two different versions (xxx_user.ini and xxx_default.ini). DO NOT edit the default version. You can lose all your settings when updating. Instead, copy any settings you want to change into the respective user file and change it there. The user file does not have to contain all settings, but only those you want to be changed.

This can be done inside the GUI under the "Preferences" menu. "Reload Settings" reloads the settings at runtime. Most settings (not all of them) can be changed at run time this way.

Recommended settings to customize: app - Customize the size the app starts in depending on your resolution. paths - Customize the search path for data for quicker access.

Usage

Before running, make sure you are in the correct environment in which you installed kMap.py. If you decided to use the venv kMap.py comes with, this corresponds to 4. Activate Environment.

To start kMap.py simply run

python -m kmap

Tutorial videos demonstrating the most important features of kMap.py can be found here: https://www.youtube.com/playlist?list=PLAoZOqtibC5ypO57SU4emdelPzSGQRO8c

Updating

Major releases for kMap.py are distributed via the PyPI Server (pip install). The source code and all minor updates with it are hosted on GitHub (https://github.com/brands-d/kMap). If you cloned the project using git executing

git pull origin master

will update the project to the most recent release. If you downloaded the .zip file in section 2. Clone Git Project manually, please download it again from the GitHub page and follow the installation instructions. Copy and replace your user settings files from the old version to the new version.

The project is currently structured into a "master" branch (release), a "dev" branch (beta) and various working branches (experimental) usually named after the person working on it. It is not recommended to clone from those branches.

Bug Report

Bug reports are highly appreciated. Please first run the

make report

command (only Linux, no equivalent for Windows currently). This will create a report.tar.gz file containing relevant files like the log files and your settings. Please add this file to any bug report! (Windows: Until an easy solution is added please attach the log file (default.log) to your bug report). Please note that this process might take a while since all tests will be run.

Simply send this file via E-mail to one of the authors ([email protected]).

Troubleshooting

A list of problems users had before and how they solved it:

Ubuntu (LTS 20.04)

ImportError: /lib/x86_64-linux-gnu/libQt5Core.so.5: version 'Qt_5.15' not found

pip install pyqt5 --force-reinstall --no-cache

Anaconda

No frame on the MainWindow or libEGL warning: MESA-LOADER: failed to open iris: /usr/lib/dri/iris_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:$${ORIGIN}/dri:/usr/lib/dri, suffix _dri)

At the following to your .bashrc or whatever shell you are using. (see here)

export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6

Windows

ImportError: DLL load failed while importing QtGui: The specified procedure could not be found.

Origin is not clear. Make sure you have python 3.8.x installed (not 3.7) and force reinstall PyQt5 in your enviroment: pip uninstall pyqt5 pip install pyqt5 --force-reinstall --no-cache

Project Structure

The root folder of the kMap.py source code should contain after successful installation at least the following files and directories:

  • /dist
  • /docs
  • /example
  • /kmap
  • .gitignore
  • LICENSE.md
  • Makefile
  • README.md
  • Manifest.in
  • setup.py

/dist

Contains the distribution versions of major releases in wheel and tar.gz form.

/docs

The /docs subdirectory contains documentation regarding the project. This includes a style guide, class- and package-diagrams as well as a description of the .hdf5 file structure.

/example

The /example subdirectory contains example data (/example/data) and example scripts (/example/scripts). The scripts are both a show-off what is possible and a tutorial of how to do various things with kMap.py. Check out the file /example/scripts/README for further information.

/kmap

This is the main folder for the program itself. It contains all the code and tests split into the following subdirectories:

  • /config
  • /controller
  • /library
  • /model
  • /resources
  • /tests
  • /ui

The source code roughly follows the MVC (model-view-controller) design pattern. However, due to various reasons, this separation is not strictly followed all the time.

/config

This directory contains all the configuration files as well as the "config" class responsible for loading, parsing and providing the settings throughout the rest of the program.

/controller

This directory contains all the controller classes and is somewhat the heart of the kMap.py program.

Pretty much every feature/GUI element has its own controller class. Controller classes (as in MCV) contain everything not suited or possible in model classes or .ui files. They handle the interaction with other elements, signals/slots, creation and destruction, some necessary GUI editing as well as quick and minor calculations.

/library

This directory contains various base classes.

The most important classes are:

  • misc.py: This file contains various general methods and useful methods used at different parts of kMap.py.
  • orbital.py: This class is responsible for loading .cube files, calculating momentum maps from the simulation data and providing an easy interface to other parts of the program.
  • plotdata.py: All image-like data plotted in kMap.py is based on this class. It provides additional core attributes (like axis information) and core functionality like interpolation and smoothing.
  • sliceddata.py : This class defines sliced-data as a 3D data set with axis information usually constructed out of .hdf5 experimental data.

/model

This directory contains model classes (as in MCV) for various more complex controller classes.

Model classes encapsulate more complex handling of data from the more general organisational matters dealt with by the controller classes themselves. They are completely removed from handling GUI elements or interacting with other elements and only get, store, edit and provide an interface to data. Therefore most controller classes don't need such a model class.

/resources

This directory contains different types of additional resources for the program to run (like the icon image file).

/tests

This directory contains all the tests available.

Each file contains one or more test classes based on the unittest module. Run them through the "make test-all" command or individually by "python -m unittest kmap/tests/xxx" where "xxx" denotes the file containing the class you want to test.

/ui

This directory contains all the .ui files exported by QtCreator and imported and parsed by the classes in the /controller directory.

The .ui files represent the view part in the MVC pattern. They are auto-generated by QtCreator, a program with an open-source license option to easily and simply create Qt-based GUIs. The files are written in a .xml format and can be opened, viewed and edited by the QtCreator program.

With some exceptions, all GUI related things are defined here (in QtCreator).

kmap's People

Contributors

brands-d avatar cskern avatar peterpuschnig avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

kmap's Issues

Use pathlib through kMap.py

Currently, QDir is used for OS independent paths. pathlib is a more suitable python package (not third party) package already used for the scripts.

Imports in example scripts

There is an ongoing issue with the import of modules in the example scripts. Figure out an elegant way of making kmap importable outside the package as well.

Bug Report Xiaosheng #2

Start kmap via python -m kmap, File-Choose sliced data-From
hnu-dependence, then if I close the the load .cube files online window
directly, I get
2020/09/30-10:04:04-kmap-ERROR Couldn't load URL
2020/09/30-10:04:04-kmap-ERROR Traceback (most recent call last):
File "C:\Users\xia.yang\Programs\kMap\kmap\controller\tabwidget.py",
line 77, in open_sliced_data_tab_by_URL
tab = SlicedDataTab.init_from_URL(URL)
File
"C:\Users\xia.yang\Programs\kMap\kmap\controller\sliceddatatab.py", line
53, in init_from_URL
model.load_data_from_URL(URL)
File
"C:\Users\xia.yang\Programs\kMap\kmap\model\sliceddatatab_model.py",
line 29, in load_data_from_URL
*orbital, options = URL
ValueError: not enough values to unpack (expected at least 1, got 0)

Add option to not set any paths

Setting a path for saving files supposedly overwrites the OS ability to remember the path of the last file saved.
Adding the "None" option for path settings should re-enable this.

Publish kMap.py on the PyPI

Publishing kMap.py on the Python Package Index would allow users to install kMap.py via a simple pip install command. This would make installation and distribution a lot easier.

Logging

The logging system is in place but not really used yet. Write and place many more log messages throughout the program.

Save project

Implement a "Save Project" feature that saves and loads all current settings inside kMap.py

Swap Axis Bug

When swaping axes and changing the slice axis the labels aren't correct anymore.

Bug Report Xiaosheng #3

Start kmap via python -m kmap, File-Choose sliced data-From orbitals
(or From hnu-dependence), then if I close the main window directly, the
options window and then close the load .cube files online window remain.
No error code.

These are related to how the pop-up windows are handled, I guess. I
think the scenario No.3 means that the options window and then close the
load .cube files online window are not children of the main window. In
python, I was not very clear what happened with deleteLater() method
when I was working on mozi. To be predictable, I did the following: the
main window is responsible for all pop-up windows as parent-child. Every
created child is sent into a container dict of the main window, where
the python id() of the child is the key. When the child window is
closed, the closeEvent() deletes the entry from the dict. If the main
windows closes, all child windows all close. You can check in the new
mozi master:
saveId() and closeEvent() in any file under \controller
window_into_container() and closeEvent() in Mozi.py
Maybe not the best solution, but my experience is it is more reliable
then deleteLater().

Bug when starting up v1.13.0

Traceback (most recent call last):
File "/home/user/anaconda3/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"main", mod_spec)
File "/home/user/anaconda3/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/user/git/kMap/kmap/main.py", line 2, in
from kmap.kMap import kMap
File "/home/user/git/kMap/kmap/kMap.py", line 93
if (path := config.get_key('paths', 'matplotlib')) != 'None':

Bug when fitting E_kin

"could not broadcast input array from shape (1052) into shape (1060)" error message when trying to fit E_kin.

Bug Report Xiaosheng #1

Start kmap via python -m kmap, File-Choose sliced data-From orbitals
(or From hnu-dependence), then if I close the options window and then
close the load .cube files online window, without doing anything. I have:
Traceback (most recent call last):
File
"C:\Users\xia.yang\Programs\kMap\kmap\controller\databasewindows.py",
line 268, in closeEvent
self.options.deleteLater()
RuntimeError: wrapped C/C++ object of type SlicedDataBaseOptions has
been deleted

Colormaps could not be loaded

Error while run the current dev version on Windows 10, 20H2
C:\resources\misc\colormaps.json\colormaps_default.json is not found

(base) C:\Users\admin\Programs\kMap>python -m kmap
2020/11/25-10:13:50-kmap-ERROR  Colormaps could not be loaded
2020/11/25-10:13:50-kmap-ERROR  Traceback (most recent call last):
  File "C:\Users\admin\Programs\kMap\kmap\controller\colormap.py", line 42, in load_colormaps
    self.model.load_colormaps(self.path)
  File "C:\Users\admin\Programs\kMap\kmap\model\colormap_model.py", line 24, in load_colormaps
    with open(path, 'r') as file:
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\resources\\misc\\colormaps.json\\colormaps_default.json'

Traceback (most recent call last):
  File "C:\Users\admin\Programs\kMap\kmap\controller\mainwindow.py", line 183, in open_orbital_data_tab
    self.tab_widget.open_orbital_data_tab()
  File "C:\Users\admin\Programs\kMap\kmap\controller\tabwidget.py", line 109, in open_orbital_data_tab
    tab = OrbitalDataTab()
  File "C:\Users\admin\Programs\kMap\kmap\controller\orbitaldatatab.py", line 37, in __init__
    self._setup()
  File "C:\Users\admin\Programs\kMap\kmap\controller\orbitaldatatab.py", line 242, in _setup
    self.colormap = Colormap([self.plot_item])
  File "C:\Users\admin\Programs\kMap\kmap\controller\colormap.py", line 37, in __init__
    self.load_colormaps()
  File "C:\Users\admin\Programs\kMap\kmap\controller\colormap.py", line 52, in load_colormaps
    self.set_default_colormap()
  File "C:\Users\admin\Programs\kMap\kmap\controller\colormap.py", line 114, in set_default_colormap
    self.set_colormap(default_colormap)
  File "C:\Users\admin\Programs\kMap\kmap\controller\colormap.py", line 108, in set_colormap
    self.model.set_current_colormap(name)
  File "C:\Users\admin\Programs\kMap\kmap\model\colormap_model.py", line 81, in set_current_colormap
    index = self._name_to_index(name)
  File "C:\Users\admin\Programs\kMap\kmap\model\colormap_model.py", line 91, in _name_to_index
    index = name_list.index(name)
ValueError: 'standard' is not in list

LUT export not correct

The LUT of pyqtgraph plots does not get properly exported to matplotlib resulting in different colorscales.

Add Database ID to tooltips

Some orbitals have the same short name. To distinguish them more easily the ID used in the database should be shown in the tooltip for the orbital.

Matplotlib export for line plots

It would be useful to display line plots (i.e. profile plot and result plot of lmfit tab) in a matplotlib window as is possible with plots.

Duplicate tabs

Feature Request: The possibility to duplicate tabs with all their settings.

Negative Values for |A.k|^2

Low angles of incidence can lead to negative values in the polarisation factor |A.k|^2 for the Nano-ESCA: He-lamp.

Tooltips

Documentation is needed: More and better tooltips for all or most features in kMap.py

Feature Request Xiaosheng #1

right now the sliced data cube is displayed in this way: when moving
the slide, the color scale is also changed to maximize the contrast of
each slice. Is there a way to fix the min/max for all slices, so when
the user sees the relative intensity between the slices. This can be an
option.

Add option on SlicedData-Tab to transpose the plotdata-array

It would be convenient to have the possibility to transpose the data shown on the SlicedData-Tab, that is, interchange the x-and y-axes. For instance, on the example4 and example5 datasets, the kx-axis is vertical and the ky-axis is horizontal. For instance, with a check-box "transpose" kx and ky should be interchanged.

Export to hdf5

Make different tabs, most importantly sliced data generated from orbitals, exportable (and loadable) as .hdf5 files.

Manually install with python setup.py install

Tried to make a new installation with python setup.py install, while having a slightly different package version, e.g. matplotlib=3.3.3 instead of 3.3.0. It seems like after install kmap, the script tries to still install the packages according to requirements.txt. Is it as intended?

(base) C:\Users\admin\Programs\kMap>python setup.py install
C:\Users\admin\Miniconda3\lib\site-packages\setuptools\dist.py:452: UserWarning: Normalizing '1.5.0-b' to '1.5.0b0'
  warnings.warn(tmpl.format(**locals()))
running install
running bdist_egg
running egg_info
writing kMap.egg-info\PKG-INFO
writing dependency_links to kMap.egg-info\dependency_links.txt
writing requirements to kMap.egg-info\requires.txt
writing top-level names to kMap.egg-info\top_level.txt
reading manifest file 'kMap.egg-info\SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'kMap.egg-info\SOURCES.txt'
installing library code to build\bdist.win-amd64\egg
running install_lib
running build_py
copying kmap\kMap.py -> build\lib\kmap
copying kmap\__init__.py -> build\lib\kmap
copying kmap\config\config.py -> build\lib\kmap\config
......
......
byte-compiling build\bdist.win-amd64\egg\kmap\tests\__init__.py to __init__.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\kmap\__init__.py to __init__.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\kmap\__main__.py to __main__.cpython-38.pyc
creating build\bdist.win-amd64\egg\EGG-INFO
copying kMap.egg-info\PKG-INFO -> build\bdist.win-amd64\egg\EGG-INFO
copying kMap.egg-info\SOURCES.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying kMap.egg-info\dependency_links.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying kMap.egg-info\not-zip-safe -> build\bdist.win-amd64\egg\EGG-INFO
copying kMap.egg-info\requires.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying kMap.egg-info\top_level.txt -> build\bdist.win-amd64\egg\EGG-INFO
creating 'dist\kMap-1.5.0b0-py3.8.egg' and adding 'build\bdist.win-amd64\egg' to it
removing 'build\bdist.win-amd64\egg' (and everything under it)
Processing kMap-1.5.0b0-py3.8.egg
creating c:\users\admin\miniconda3\lib\site-packages\kMap-1.5.0b0-py3.8.egg
Extracting kMap-1.5.0b0-py3.8.egg to c:\users\admin\miniconda3\lib\site-packages
Adding kMap 1.5.0b0 to easy-install.pth file

Installed c:\users\admin\miniconda3\lib\site-packages\kmap-1.5.0b0-py3.8.egg
Processing dependencies for kMap==1.5.0b0
Searching for PyQt5==5.15.0
Reading https://pypi.org/simple/PyQt5/
Downloading https://files.pythonhosted.org/packages/7c/06/0b3cbfd63fc6cbd3585d1a3b2729055e19c646ae329050e174e3c29a4741/PyQt5-5.15.0-5.15.0-cp35.cp36.cp37.cp38-none-win_amd64.whl#sha256=5bac0fab1e9891d73400c2470a9cb810e6bdbc7027a84ae4d3ec83436f1109ec
Best match: PyQt5 5.15.0
Processing PyQt5-5.15.0-5.15.0-cp35.cp36.cp37.cp38-none-win_amd64.whl
Installing PyQt5-5.15.0-5.15.0-cp35.cp36.cp37.cp38-none-win_amd64.whl to c:\users\admin\miniconda3\lib\site-packages
Adding PyQt5 5.15.0 to easy-install.pth file
Installing pylupdate5-script.py script to C:\Users\admin\Miniconda3\Scripts
Installing pylupdate5.exe script to C:\Users\admin\Miniconda3\Scripts
Installing pyrcc5-script.py script to C:\Users\admin\Miniconda3\Scripts
Installing pyrcc5.exe script to C:\Users\admin\Miniconda3\Scripts
Installing pyuic5-script.py script to C:\Users\admin\Miniconda3\Scripts
Installing pyuic5.exe script to C:\Users\admin\Miniconda3\Scripts

Installed c:\users\admin\miniconda3\lib\site-packages\pyqt5-5.15.0-py3.8-win-amd64.egg
Searching for numpy==1.19.0
Reading https://pypi.org/simple/numpy/
Downloading https://files.pythonhosted.org/packages/df/f3/3fdea08ad680100b5e7abf810a154ce142a63266df1abfdca5cb0f66cca1/numpy-1.19.0-cp38-cp38-win_amd64.whl#sha256=c2edbb783c841e36ca0fa159f0ae97a88ce8137fb3a6cd82eae77349ba4b607b
Best match: numpy 1.19.0
Processing numpy-1.19.0-cp38-cp38-win_amd64.whl
Installing numpy-1.19.0-cp38-cp38-win_amd64.whl to c:\users\admin\miniconda3\lib\site-packages
Adding numpy 1.19.0 to easy-install.pth file
Installing f2py-script.py script to C:\Users\admin\Miniconda3\Scripts
Installing f2py.exe script to C:\Users\admin\Miniconda3\Scripts

Installed c:\users\admin\miniconda3\lib\site-packages\numpy-1.19.0-py3.8-win-amd64.egg
Searching for matplotlib==3.3.0
Reading https://pypi.org/simple/matplotlib/
Downloading https://files.pythonhosted.org/packages/a3/f0/0e5f5fe42696aef6a5ab7555658f700ea1caee51406751e559b596dbb70d/matplotlib-3.3.0-cp38-cp38-win_amd64.whl#sha256=2a9d10930406748b50f60c5fa74c399a1c1080aa6ce6e3fe5f38473b02f6f06d
interrupted

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.