Giter Site home page Giter Site logo

aiidalab-qe-vibroscopy's People

Contributors

andresortegaguerrero avatar mikibonacci avatar superstar54 avatar

Stargazers

 avatar

Watchers

 avatar

Forkers

superstar54

aiidalab-qe-vibroscopy's Issues

Allowing multiple properties in the same run

  • multiple spectra wanted: needed two simulation for dielectric tensors.
  • multiple phonon properties: more phonopy calculations at the end of the phononworkchain (or harmonic one)
  • multiple dielectric tensors.

==> we should introduce this logic in the VibroWorkChain, I think.

SelectMultiple in togglebuttons.

Discussion with Lorenzo

pinning @AndresOrtegaGuerrero. This was a summary written by Lorenzo, after very fruitful discussion some day ago:

AiiDAlab for vibrational properties and spectroscopies:
Discussed thoroughly the theory and implementation of the aiida-vibroscopy package
From v1.1.0, aiida-vibroscopy will implement the complex dielectric tensor (IR regime) --> normal reflectivity, absorption and ELS

  • Useful properties to have in the app for experimentalists:

Raman spectra:
Single-crystal polarized: units of the incoming/outgoing light polarization --> crystal unit cell coordinates; q-direction = kin-kout (crystal unit cell coordinates)

Unpolarized spectra (used also for powder in centrosymmetric crystals): divided in HH/VV and HV setups, the two common experimental setups; powder spectra is the sum of the two

Powder spectra for non-centrosymmetric crystals: this is the sum of the unpolarized spectra averaged among all the possible q-direction (done via the IntensitiesAverageWorkChain or via API of VibrationalData)
Useful to have polarized spectra with rotation of the crystal/light polarization: very interesting for 2D materials; common setups are parallel and orthogonal polarization, and then rotation around the orhtogonal direction by angle theta

IR spectra:
Single crystal polarized (as for Raman, but only 1 polarization direction)
Unpolarized spectra and powder spectra, as for Raman
Complex dielectric function:
From this you can compute: normal reflectance, absorption (i.e. IR spectra), ELS (this one is still not implemented, but very easy to do, as it is ~Re 1/epsilon(w) )

Useful to tell how many supercells with displacements are going to be computed; this number doesn't depend on supercell size (check also Baroni 2001). To get this, use PreProcessData(...).displacements to get the number of displacements

The HarmonicWorkChain does the same job as ph.x: computes phonons in supercell (PhononWorkChain), and dielectric properties (Born charges, dielectric, Raman, non-linear-optical susceptibilit (Chi^(2)) tensors)

The IRamanSpectraWorkChain simple calls HarmonicWorkChain imposing supercell_matrix: [1,1,1], as it need phonons only at Gamma

If the HarmonicWorkChain is used given dielectric.property: 'raman' as input, then you also have everything for Raman

In conclusion, it's easier to:
Always tell to compute IR (complex dielectric function) and Raman together
Possibly implement interface for DielectricWorkChain in case dielectric properties (eps^infty and Chi^(2)) are of interest
Insulator needs the NAC (Born charges, dielectric tensors) to interpolate well the phonon band structure --> insert a flag insulator/metal and activate automatically (you need to call HarmonicWorkChain with dielectric properties, at least second order derivatives here)?

No module named 'widget_bandsplot'

I ran QEApp in the edge image, aiida-core 2.5.1, QEApp 2024.04.0.rc1, and got this error.

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
/tmp/ipykernel_6599/2609984044.py in <cell line: 19>()
     17 from jinja2 import Environment
     18 
---> 19 from aiidalab_qe.app import App, static
     20 from aiidalab_qe.version import __version__

~/.local/lib/python3.9/site-packages/aiidalab_qe/app/__init__.py in <module>
      1 """Package for the AiiDAlab QE app."""
      2 
----> 3 from .main import App
      4 
      5 __all__ = [

~/.local/lib/python3.9/site-packages/aiidalab_qe/app/main.py in <module>
     12 from aiidalab_qe.app.result import ViewQeAppWorkChainStatusAndResultsStep
     13 from aiidalab_qe.app.structure import StructureSelectionStep
---> 14 from aiidalab_qe.app.submission import SubmitQeAppWorkChainStep
     15 from aiidalab_qe.common import QeAppWorkChainSelector
     16 

~/.local/lib/python3.9/site-packages/aiidalab_qe/app/submission/__init__.py in <module>
     23     QEAppComputationalResourcesWidget,
     24 )
---> 25 from aiidalab_qe.workflows import QeAppWorkChain
     26 
     27 

~/.local/lib/python3.9/site-packages/aiidalab_qe/workflows/__init__.py in <module>
     41 
     42 
---> 43 plugin_entries = get_entry_items("aiidalab_qe.properties", "workchain")
     44 
     45 

~/.local/lib/python3.9/site-packages/aiidalab_qe/workflows/__init__.py in get_entry_items(entry_point_name, item_name)
     33 # load entry point items
     34 def get_entry_items(entry_point_name, item_name="workchain"):
---> 35     entries = get_entries(entry_point_name)
     36     return {
     37         name: entry_point.get(item_name)

~/.local/lib/python3.9/site-packages/aiidalab_qe/workflows/__init__.py in get_entries(entry_point_name)
     26     entries = {}
     27     for entry_point in entry_points().get(entry_point_name, []):
---> 28         entries[entry_point.name] = entry_point.load()
     29 
     30     return entries

/opt/conda/lib/python3.9/site-packages/importlib_metadata/__init__.py in load(self)
    207         """
    208         match = self.pattern.match(self.value)
--> 209         module = import_module(match.group('module'))
    210         attrs = filter(None, (match.group('attr') or '').split('.'))
    211         return functools.reduce(getattr, attrs, module)

/opt/conda/lib/python3.9/importlib/__init__.py in import_module(name, package)
    125                 break
    126             level += 1
--> 127     return _bootstrap._gcd_import(name[level:], package, level)
    128 
    129 

~/.local/lib/python3.9/site-packages/aiidalab_qe_vibroscopy/app/__init__.py in <module>
      1 from aiidalab_qe_vibroscopy.app.settings import Setting
      2 from aiidalab_qe_vibroscopy.app.workchain import workchain_and_builder
----> 3 from aiidalab_qe_vibroscopy.app.result import Result
      4 from aiidalab_qe.common.panel import OutlinePanel
      5 

~/.local/lib/python3.9/site-packages/aiidalab_qe_vibroscopy/app/result.py in <module>
      5 
      6 
----> 7 from widget_bandsplot import BandsPlotWidget
      8 
      9 from aiidalab_qe.common.panel import ResultPanel

ModuleNotFoundError: No module named 'widget_bandsplot'

Improvements on workchain (1): changing the logic

This derives from #33.
Basically, we should just provide 4 possibilities, as described in the above mentioned issue.

  • provide the transfer of the logic from settings to workchain, then to vibroworkchain.
  • limitation on the outputs exposed in VibroWorkChain: this will require, in the result step, to call the vibroworkchain_node.called[0] to be able to access the output nodes.
  • support for output Results to work with the new expose outputs.

Installation problem

After using the "/aiidalab/full-stack:latest" image

Stored in directory: /tmp/pip-ephem-wheel-cache-p5nkviqk/wheels/da/ce/0a/3c41782f94eb55d1e07b0e85018734d854465ae85a469a3125
Building wheel for h5py (pyproject.toml) ... error
error: subprocess-exited-with-error

× Building wheel for h5py (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [73 lines of output]
running bdist_wheel
running build
running build_py
creating build
creating build/lib.linux-aarch64-cpython-39
creating build/lib.linux-aarch64-cpython-39/h5py
copying h5py/h5py_warnings.py -> build/lib.linux-aarch64-cpython-39/h5py
copying h5py/ipy_completer.py -> build/lib.linux-aarch64-cpython-39/h5py
copying h5py/version.py -> build/lib.linux-aarch64-cpython-39/h5py
copying h5py/init.py -> build/lib.linux-aarch64-cpython-39/h5py
creating build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/compat.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/files.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/base.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/filters.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/attrs.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/selections2.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/dims.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/datatype.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/dataset.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/vds.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/selections.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/group.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
copying h5py/_hl/init.py -> build/lib.linux-aarch64-cpython-39/h5py/_hl
creating build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5p.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_filters.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_file_image.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_selections.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_slicing.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5z.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_ros3.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/conftest.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_completions.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_dataset.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5o.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_file2.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_dimension_scales.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_dims_dimensionproxy.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_dataset_swmr.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_objects.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_group.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_dataset_getitem.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_errors.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_file_alignment.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5d_direct_chunk.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_datatype.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5f.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_attrs_data.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_base.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_big_endian_file.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_file.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_attribute_create.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5t.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5pl.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/common.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_h5.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/init.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_dtype.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
copying h5py/tests/test_attrs.py -> build/lib.linux-aarch64-cpython-39/h5py/tests
creating build/lib.linux-aarch64-cpython-39/h5py/tests/data_files
copying h5py/tests/data_files/init.py -> build/lib.linux-aarch64-cpython-39/h5py/tests/data_files
creating build/lib.linux-aarch64-cpython-39/h5py/tests/test_vds
copying h5py/tests/test_vds/test_highlevel_vds.py -> build/lib.linux-aarch64-cpython-39/h5py/tests/test_vds
copying h5py/tests/test_vds/test_lowlevel_vds.py -> build/lib.linux-aarch64-cpython-39/h5py/tests/test_vds
copying h5py/tests/test_vds/test_virtual_source.py -> build/lib.linux-aarch64-cpython-39/h5py/tests/test_vds
copying h5py/tests/test_vds/init.py -> build/lib.linux-aarch64-cpython-39/h5py/tests/test_vds
copying h5py/tests/data_files/vlen_string_dset.h5 -> build/lib.linux-aarch64-cpython-39/h5py/tests/data_files
copying h5py/tests/data_files/vlen_string_dset_utc.h5 -> build/lib.linux-aarch64-cpython-39/h5py/tests/data_files
copying h5py/tests/data_files/vlen_string_s390x.h5 -> build/lib.linux-aarch64-cpython-39/h5py/tests/data_files
running build_ext
Building h5py requires pkg-config unless the HDF5 path is explicitly specified using the environment variable HDF5_DIR. For more information and details, see https://docs.h5py.org/en/stable/build.html#custom-installation
error: pkg-config probably not installed: FileNotFoundError(2, 'No such file or directory')
[end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for h5py
Successfully built aiidalab-qe-vibroscopy
Failed to build h5py
ERROR: Could not build wheels for h5py, which is required to install pyproject.toml-based projects

'PhononBandPdosPlotly' object has no attribute '_create_combined_plot'

I did a test calculation using Si, the calculation finished successfully, but I got error when visualizing the result.

AttributeError                            Traceback (most recent call last)
~/.local/lib/python3.9/site-packages/aiidalab_widgets_base/viewers.py in _observe_node(self, change)
     78                 clear_output()
     79                 if change["new"]:
---> 80                     display(viewer(change["new"]))
     81 
     82 

~/.local/lib/python3.9/site-packages/aiidalab_widgets_base/viewers.py in viewer(obj, **kwargs)
     54 
     55     if _viewer:
---> 56         return _viewer(obj, **kwargs)
     57     else:
     58         # No viewer registered for this type, return object itself

~/.local/lib/python3.9/site-packages/aiidalab_qe/app/result/workchain_viewer.py in __init__(self, node, **kwargs)
     84 
     85         self.result_tabs.observe(on_selected_index_change, "selected_index")
---> 86         self._update_view()
     87 
     88         super().__init__(

~/.local/lib/python3.9/site-packages/aiidalab_qe/app/result/workchain_viewer.py in _update_view(self)
    123                     ]
    124                     if all(results_ready):
--> 125                         result._update_view()
    126                         self._results_shown.add(result.identifier)
    127                         # add this plugin result panel

~/.local/lib/python3.9/site-packages/aiidalab_qe_vibroscopy/app/result.py in _update_view(self)
     93                     pdos_data=phonon_data["pdos"][0],
     94                 )
---> 95                 phonon_children += (_bands_plot_view_class._create_combined_plot(),)
     96 
     97             if phonon_data["thermo"]:

AttributeError: 'PhononBandPdosPlotly' object has no attribute '_create_combined_plot'

Improvements on settings (2): supercell hints and estimation of the number of supercells to be computed

This can greatly improve user experience in the determination of the settings

1 - hint on the supercell dimensions (15-20-25 A or 100-300 atoms --- maybe connected to the protocol selected in basic settings);
2- related estimation of the number of simulations to be done, both in terms of displacements and of electric field (if dielectric is required);

  • supercell hint widget (something similar to the one contained in aiidalab-qe-muon);

  • usage of the PreProcessData in aiida-phonopy to estimate the number of supercells;

  • add the possibility to set the parameters on this estimation, e.g. symmetry tolerance. These parameters should be then linked to the WorkChain inputs;

  • also kpoints mesh for SC. check if this works for 3D, 2D, 1D...

Improvements on result (2): having a separated app for INS?

This was asked from an experimental colleague: to have some aiida-detached app in aiidalab, where to just upload the yaml file and plot the neutron spectra. This can be rather easy in case, as we can reuse the euphonic widgets.

Anyway, the INS spectra will be available in the qe app.

  • button for plots? or we plot by default?

Improvements on results (5): additional features for Neutron scattering

  • choosing the q for plots: for experimentalists is common to do not have the Gamma in the iBZ, but in outer zones. So, it can be useful to define the path by hands, like: (0,0,2) -> (0,0,3) .... and so on. Similar to what is done in bands but with vectors, not letters.
  • Constant energy slice plots: plot the S(q,w) in a particular plane in the 3d q space. definition of the plane (3 q points) and of a maximum q distance. Or, define 4 points to detect a square. Definition of a mesh grid.
  • make feasible to download the intensity maps: the json file seems to be to heavy...compress? or change filetype?

To have examples on the output plots: https://journals.aps.org/prb/abstract/10.1103/PhysRevB.106.224304

Display which workchain property is run

When selecting the workchain in aiidalab-qe , instead of displaying vibronic , it should display the property, like iraman, phonon bands, phonons pdos, dielectric constant ....

Improve logic in WorkChain

File "/opt/conda/lib/python3.9/site-packages/plumpy/process_states.py", line 228, in execute
result = self.run_fn(*self.args, **self.kwargs)
File "/opt/conda/lib/python3.9/site-packages/aiida/engine/processes/workchains/workchain.py", line 314, in _do_step
finished, stepper_result = self._stepper.step()
File "/opt/conda/lib/python3.9/site-packages/plumpy/workchains.py", line 295, in step
finished, result = self._child_stepper.step()
File "/opt/conda/lib/python3.9/site-packages/plumpy/workchains.py", line 438, in step
finished, retval = self._child_stepper.step()
File "/opt/conda/lib/python3.9/site-packages/plumpy/workchains.py", line 295, in step
finished, result = self._child_stepper.step()
File "/opt/conda/lib/python3.9/site-packages/plumpy/workchains.py", line 246, in step
return True, self._fn(self._workchain)
File "/home/jovyan/aiidalab-qe-vibroscopy/aiidalab_qe_vibroscopy/workflows/vibroworkchain.py", line 667, in run_phonopy
inputs = self.ctx.phonopy.copy(
TypeError: AttributeDict.copy() takes no keyword arguments

This error is triggered, maybe , by doing a verdi daemon restart (when the workflow is at this stage?)

Settings Summary

The Result Panel should display a HTML table with the parameters and settings selected

Phonon Pdos projections

The experimentalis are interest to have different projections for the phonon pdos.
For example to select some atoms, and obtained the contribution of those atoms in pdos

expose vibroscopy nodes to output widgets

  • I would like to provide to the widgets only nodes coming from the aiida-vibroscopy workchains, so they can be used also outside the app in case. This may be a problem for app tests, but we will see in that case.
  • As additional task, I would like to put the number of the mode in the table, so I can easily go to the dropdown and select

handling extra plugins

When installing this plugin in the app, it should install aiida-phonopy and aiida-vibroscopy plugins

Results panel functionalities and more

  • output dielectric properties not shown - ANDRES
  • Raman and IR in the same output, can choose what to plot on the fly
  • bands and dos plots: this is related to multiple phonopy runs in one simulation. This has to be done at the VibroWorkChain level (in the app-plugin) --> understand how to re-generate phonopy.yaml. - MIKI
  • exposing too many outputs if big systems. problem of vibronic outputs: it takes time.
  • click on bands and see animation (see materials cloud, but be sure javascript supported) - MIKI and ANDRES
  • downloadable spectra
  • interactive raman (Temperature, energy of the incoming light)

Less critical - no real issues -:

  • number of supercell estimation in the settings phase
  • zoomed out modes in raman animation
  • arrows/lines shown in the animation, but is slow: maybe a rendered image on demand (button)? see osscar

Output widgets only working for Raman

I noticed that the now output widgets only works for Raman.
I am opening an issue because I do not have time right now to fix it but I do not want to forget.

Improvements on the settings (1): choice of the properties

This should consider different possibility, and will determine the logic of the VibroWorkchain. The VibroWorkChain may also be splitted in the standard aiida-vibroscopy ones, referring to #22.

  •  Specift that we are in first order non-resonant Raman scattering regime (maybe only when Raman is selected).
  • specify what properties can be computed (bands, dos, INS...)

The properties will be grouped in this way:

  • Raman, IR, Dielectric, INS**, Phonons (bands, pdos, thermal): HarmonicWorkChain - heavier computational cost, as Raman and IR are then computed in supercell approach (also q!=0 phonons);
  • Raman, IR, Dielectric: primitive cell approach. We always compute both (IRamanWorkChain, dielectric.property="raman"), as the third order derivatives does not introduce too large additional computational cost;
  • INS**, Phonons (bands, pdos, thermal): supercell approach, can be both polar (HarmonicWorkChain, with dielectric properties) or not (PhononWorkChain);
  •  Dielectric properties only: compute up to third order (DielectricWorkChain, dielectric.property="raman");

** The inelastic neutron scattering (INS) is just a post processing from phonons.

Improvements on results (1): Phonopy versus Euphonic for phonon processing

in the pro_Euphonic branch, bands and dos are performed using euphonic code. However, we should check if this represents a real advantage or not.

  • test performance phonopy vs euphonic, increasing meshes for properties
  • define if phonopy should run at the end of a calculation (Harmonic/PhononWorkchain), and for what.
  • working result panel within the new logic of exposing outputs
  • give to euphonic not the yaml but create the yaml on the fly

Anyway, for the inelastic neutron scattering part, euphonic will be used.

Improvement on results (3): Raman and IR spectra parameters and polar plots

Raman and IR spectra improvement:

  • show both IR and Raman: now we should have them at the same time
  • add reset button for parameters
  • #45
  • all properties should be downloadable (also phononic one... for now this is not true)

In principle, it is possible to define HH/VV and HV geometries for the scattering spectra (backward or 90 degree deviation geometries). In principle, this can be defined as input when spectra are computed; #43

  • Intensity average workchain.
  • understand how you can define these in/out directions in the functions. In principle this can be defined via q=k_in-k_out

the light polarization is another thing, and is the one already defined in our widgets.

Polar plots:

In principle, one can define the spectra intensity for a range of polarization, being then angle dependent, and plot in a so-called polar plot. We should define input and output polarization in function of this angle, and plot for [0,2pi]/N, where N is the number of point on the cirumference.

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.