Git Product home page Git Product logo

pyroll-core's People

Contributors

axtimhaus avatar chren95 avatar msch67 avatar richardpfr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyroll-core's Issues

Provide a helper-function for 3-roll process to calculate gap-value from inner circle

Summary

For 3-roll processes the actual rollposition is specified by providing a innerdiameter rather than the gap-value.

PyRolL should provide a method to calculate the gap-value from a given innerdiameter
or
it shoulb be spossible to simply provide the innerdiameter instead of the gap-value.

Detailed Description

Possible solution:
based on https://stackoverflow.com/questions/39840030/distance-between-point-and-a-line-from-two-points

P1 = np.array([0,0])
P2 = np.array([1, np.tan(np.radians(30))]) * convert_SI['length']

px = np.array([Stand.roll.contour_points[-1][0] for Stand in PassSequence])
py = np.array([Stand.roll.contour_points[-1][1] for Stand in PassSequence])

maxIndex = np.array([list(Stand.roll.contour_points[:,0]).index(0.0) for Stand in PassSequence])

pymax = [Stand.roll.contour_points[maxIndex[n],1] for n, Stand in enumerate(PassSequence)]

offset = InnerRadius - pymax

P3 = np.vstack((px, py + offset)).T

gap_from_Di = 2 * np.abs(np.cross(P2-P1, P1-P3)) / np.linalg.norm(P2-P1)

Unit Class Hierarchy Concept

I have created a chart visualizing the current class hierarchy of the unit classes.

I call for discussion regarding its logic and possible additions or changes.
I excluded the DeformationUnit from the chart, as it's just a common base for RollPass and RollPass.DiskElement. Including the *.DiskELement classes into the chart would end in a mess.

My personal concerns so far:

  • maybe derive also RollPass from Transport, since atmosphere contact is also present
  • the current Transport derivatives are only rough concepts by now

unit_hierarchy.png

Make certain that strain_rate is always displayed in PassSequence Summary

Summary

In analysis of forming processes temperature, strain and strain_rate are the fundamental state variables.

The PassSequence summary should alsways provide these values.

Strain_rate values seem to be available in the reults database but is not added to the Summary when a flowcurve calculation method with no strain_rate dependance is used.

Add Waterbox Unit

Summary

Adding a Waterbox base unit derived from Transport would bring us one step closer to representation of the full rolling train.

Clarify Intentions and Specifics of PyRolL in the Readme

Pay respect to suggestions of @Kevin-Mattheus-Moerman here.

"I would say that it would be great to extend your README with a bit of an explanation of what the software does. I would first briefly explain what rolling you are talking about, e.g. groove rolling. It would be great to have a graphic visualizing the rolling process. There are manual and automated groove rollers I suppose. Is your work relevant to both types? Next if you clarified what the typical inputs are, what the purpose of the simulation is, what its assumptions are (mention or refer to underlying theory), and what the typical outputs are, that would be great. Actually I would add as much visual information as possible. E.g. graphs or a table of typical outputs. I would also briefly mention what these outputs allow one to do? e.g. optimise/evaluate X for the process. At the moment as an outsider, it looks tricky to see what the software does."

Add equivalent radius and diameter to profile

Summary

Add a equivalent radius and diameter hook.

Detailed Description

As there are several models working developed for round profiles, those can be made usable if a equivalent diameter and radius is provided for the profile class. These should be calculated from a equivalent round with the same area as the original profile.

Issue with "rotation"

Summary

Simply test based on square initial profile and box gooves ending with
raise AttributeError(f"Hook call for '{self.name}' on '{instance}' could not provide a value.")
AttributeError: Hook call for 'rotation' on 'Rotator 'Auto-Rotator for RollPass 'BOX B0''' could not provide a value.

PyRolL Version and Platform

Last version of PyRoll from github

Steps to Reproduce

For reproduction I prepared this test maximal sipmle file
https://github.com/ToFFmashines/pyroll-core/blob/main/tests/test-square-to-box.py

Adding new grooves for slitting

Summary

Include grooves for slitting passes.

Detailed Description

To further expand the possible use cases of PyRolL various grooves for slitting technology should by added.
These consist of a multi-dog-bone groove as well as a upset square.
The multi-dog bone most often consists of 2 rounds and 2 oval grooves depending on the slitting type.

Further Information, Files, and Links

upset_rectange

multi-dog-bone

Ausführen des Beispielskripts mithilfe der CLI

Hallo zusammen. :D

Ich versuche gerade, eine beispielhafte Rechnung mithilfe der CLI auszuführen. Dazu habe ich pyroll in einer virtuellen Umgebung installiert (mit Poetry und dann die poetry shell aktiviert). Dann habe ich einen neuen Ordner erstellt und pyroll new ausgeführt. Danach habe ich pyroll input-py solve report ausgeführt, was mir allerdings folgenden Fehler ausspuckt:

(pyroll-gui-py3.10) PS C:\Users\hanne\Documents\Programme\pyroll-gui\pyrolltest> pyroll new
[INFO] pyroll.ui.cli.program: Created config file in: C:\Users\hanne\Documents\Programme\pyroll-gui\pyrolltest\config.yaml
[INFO] pyroll.ui.cli.program: Created input file in: C:\Users\hanne\Documents\Programme\pyroll-gui\pyrolltest\input.py
(pyroll-gui-py3.10) PS C:\Users\hanne\Documents\Programme\pyroll-gui\pyrolltest> pyroll input-py solve report
>>
[INFO] pyroll.ui.cli.program: Loaded plugins: ['pyroll.freiberg_flow_stress', 'pyroll.hensel_power_and_labour', 'pyroll.integral_thermal', 'pyroll.lendl_equivalent_method', 'pyroll.wusatowski_spreading', 'pyroll.zouhar_contact', 'pyroll.gui'].
[INFO] pyroll.ui.cli.program: Reading input from: C:\Users\hanne\Documents\Programme\pyroll-gui\pyrolltest\input.py
[INFO] pyroll.ui.cli.program: Finished reading input.
[INFO] pyroll.ui.cli.program: Starting solution process...
[INFO] pyroll.core.roll_pass.roll_pass: Started solving of RollPass 'Oval I'.
C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py:160: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  return self.get_from_hook(key)
Traceback (most recent call last):
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\solve.py", line 11, in solve
    last_profile = u.solve(last_profile)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\unit.py", line 71, in solve
    current_values = self.get_root_hook_results()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\roll_pass\roll_pass.py", line 89, in get_root_hook_results
    super_results = super().get_root_hook_results()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\unit.py", line 48, in get_root_hook_results
    out_profile_results = self.out_profile.get_root_hook_results()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 168, in get_root_hook_results 
    result = self.get_from_hook(key)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 136, in get_from_hook
    result = hook(**self.hook_args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
    return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
    return outcome.get_result()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
    raise ex[1].with_traceback(ex[2])
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
    res = hook_impl.function(*args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\integral_thermal\roll_pass_impls.py", line 27, in temperature
    return roll_pass.in_profile.temperature + roll_pass.temperature_change
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 160, in __getattr__
    return self.get_from_hook(key)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 136, in get_from_hook
    result = hook(**self.hook_args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
    return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
    return outcome.get_result()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
    raise ex[1].with_traceback(ex[2])
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
    res = hook_impl.function(*args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\integral_thermal\roll_pass_impls.py", line 76, in temperature_change
    return roll_pass.temperature_change_by_contact + roll_pass.temperature_change_by_deformation
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 160, in __getattr__
    return self.get_from_hook(key)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 136, in get_from_hook
    result = hook(**self.hook_args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
    return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
    return outcome.get_result()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
    raise ex[1].with_traceback(ex[2])
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
    res = hook_impl.function(*args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\integral_thermal\roll_pass_impls.py", line 48, in temperature_change_by_contact
    mean_density(roll_pass)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\integral_thermal\helper.py", line 9, in mean_density     
    return (unit.in_profile.density + unit.out_profile.density) / 2
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 160, in __getattr__
    return self.get_from_hook(key)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\plugin_host.py", line 136, in get_from_hook
    result = hook(**self.hook_args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
    return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
    return outcome.get_result()
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
    raise ex[1].with_traceback(ex[2])
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
    res = hook_impl.function(*args)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\integral_thermal\profile_impls.py", line 8, in density   
    raise ValueError("You must provide a density to use the pyroll-integral-thermal plugin.")
ValueError: You must provide a density to use the pyroll-integral-thermal plugin.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\Scripts\pyroll.exe\__main__.py", line 7, in <module>
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\click\core.py", line 1688, in invoke
    rv.append(sub_ctx.command.invoke(sub_ctx))
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\click\decorators.py", line 38, in new_func
    return f(get_current_context().obj, *args, **kwargs)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\ui\cli\program.py", line 129, in solve
    pyroll.core.solve(state.sequence, state.in_profile)
  File "C:\Users\hanne\Documents\Programme\pyroll-gui\.venv\lib\site-packages\pyroll\core\solve.py", line 13, in solve
    raise RuntimeError(f"Solution of pass sequence failed at unit {u}.") from e
RuntimeError: Solution of pass sequence failed at unit RollPass 'Oval I'.

Betriebssystem: Windows 10
Python-Version: 3.10

Non-Deterministioc Errors Raised by Shapely

Sometimes there occur non-deterministic errors thrown by shapely because of empty polygons or clipping rectangles. This was especially observed while using the pyroll-pillar-model plugin (currently not published) and dependents.

The reasons for this was identified in the order of root hook evaluation.
This order is not deterministic, since root_hooks is a set.
Sometimes hooks are evaluated before the first evaluation of the OutProfile.cross_section hook and use therefore the cross section of the in profile passed during initialization.
This may conflict with hooks that are evaluated later using the new cross section.

Hooks Regarding Energy Consumption

Add additional hooks regarding energy consumption such as:

  • RollPass
    • power, energy per ton
  • PassSequence
    • total power, total energy consumption

Remove total keyword from PassSequence hooks, to enable simplified nesting.

Request for strain rate in transport

Would need strain rate of roll pass for calculation of static (and metadynamic) recrystallization in jmak-module.
At the moment it is not included in the transport and therefore I can't access it.
JMAK should function apart from the issue with the strain rate.

Transport as First Unit of a Sequence Does Not Work

Summary

Inserting a Transport as the first unit of a pass sequence fails in the first RollPass with

IndexError: This unit has no previous, as it is the first one.

PyRolL Version and Platform

PyRolL 2.0.1

Expected Behavior

Should have the same behavior in the first pass as it where the first unit in the sequence, i.e. does not rotate the profile.

Actual Behavior

Index error is used.

Steps to Reproduce

sequence = PassSequence([
    Transport(duration=1),
    RollPass(
        label="Oval I",
        roll=Roll(
            groove=CircularOvalGroove(
                depth=8e-3,
                r1=6e-3,
                r2=40e-3
            ),
            nominal_radius=160e-3,
            rotational_frequency=1,
            neutral_point=-20e-3
        ),
        gap=2e-3,
    ),
    Transport(duration=1)
])

Add in_profile_velocity and out_profile_velocity to the resultlist

Summary

Add in_profile_velocity and out_profile_velocity to the resultlist

Detailed Description

The results give a velocity-value. Its exact meaning is not clear to me.

I would prefer if a distinct value for a in_profile_velocity and a out_profile_velocity could be provided.

Arbeitenden Durchmesser richtig definieren

arbeitender Durchmesser über $D_W - h_{1m}^"$ definieren !!!
Sonst ist der Walzendurchmesser für diverse Rechnungen zu groß.
Die obige Darstellung sichert, dass der reale Walzstich mit dem äquivalenten zusammenpasst.

Adding equivalent groove for rebar rolling

Summary

Adding additional groove for rebar rolling.

Detailed Description

Adding a equivalent groove for simulation of rebar rolling using geometric values of the rebar design creating a equivalent round or equivalent 3 radii oval groove.

Further Information, Files, and Links

Introduction of Pint for quantities and units

Summary

Since PyRolL currently supports all metric units but all of the "physical quantities handling" has to be done by the user, I suggest a filter layer for the import to introduce units.
This would benefit PyRolL since "simple" users don't want to think about to much stuff before doing their first simulation.
Also some model approaches (mostly the empirical ones) work in specific physical quantities.
Therefore the introduction of physical quantities would further protect PyRolL from misuse.

A possibility to introduce units is the python package pint .
This could act as a translation layer, anchored inside a own extension plugin.
First of I would like to discuss it generally.

Versionsinkompatibilität von einigen Modulen

Hallo zusammen,

ich hatte versucht, die neueste Betaversion von Pyroll von Pypi zu installieren, weil ich gesehen hatte, dass ihr den Reporter geupdated hattet und ich die neueste Betaversion verwenden möchte, damit ich den Code nicht später anpassen muss.

Allerdings geht das momentan noch nicht, da die Versionen noch nicht ganz kompatibel sind:
pyroll-zouhar-contact hängt noch von pyroll ^1.0.0 ab, was dann eine Fehlermeldung verursacht.

(Am Rande würde ich vorschlagen, die Standard-Poetry-Versionslimits (bis zur nächsten Hauptversion der dependencies, markiert mit ^) durch offene Limits >= zu ersetzen, sofern keine Inkompatibilität der betroffenen Bibliothek bekannt ist (die pyroll-Sachen vielleicht ausgenommen, wenn die synchron sein sollen.). Das ist soweit ich weiß die Schlussfolgerung von Leuten, die darüber zu viel nachgedacht haben, und ich hatte schon einmal in einem anderen Projekt durch Version Capping nervige Probleme. 😀)

Anderes Problem:
pyroll-zouhar-contact hat auch noch den 3.11 Version-Constraint, genauso wie pyroll-basic (Ich glaube, 3.11 wär für die GUI schon ziemlich cool, weil die Performance besser sein soll.)

Box groove solve_box_like function return depth = None

which fails the value check:

pyroll/core/grooves/generic_elongation.py(71)__init__()
     69         mandatory_positive_or_zero = [r1, r2, r3, r4, alpha3, alpha4, indent, even_ground_width, flank_angle,
     70                                       usable_width, ground_width, depth]
---> 71         if any(value < 0 for value in mandatory_positive_or_zero):
     72             raise ValueError("Groove arguments have to be non-negative.")

Among usable_width, ground_width, flank_angle, depth, there will be one that is none, based on the following requirement:

pyroll/core/grooves/generic_elongation.py:93, in GenericElongationGroove.__init__(self, r1, r2, flank_angle, usable_width, ground_width, depth, r3, alpha3, r4, alpha4, indent, even_ground_width, pad, rel_pad, pad_angle, classifiers)
     90         raise TypeError("Too many arguments given.")
     92 except TypeError:
---> 93     raise TypeError("Exactly three of usable_width, ground_width, flank_angle and depth must be given.")
     95 self.r1 = r1
     96 self.r2 = r2

Improve internal naming schemes to work with autocompletion in jupyter notebooks

Summary

Some internal names like e.g. ThreeRollPass 'Pass4' are incompatible with autocompletion in jupyter notebooks.
They are not displayed in the autocompletion list.

This is at times quite comfusing when looking for specific results.

It would be better if internal names are created in a way so that they support autocompletion.

image

Add Plotting Methods for RollPasses and Profiles

To enable fast interactive visual checking of profiles and roll passes (especially in notebooks) add some methods to plot them immediately in a standardized way.

  • Do not add a dependency on matplotlib.
  • Support this functionality only when matplotlib is importable.
  • Add this functionality to _repr_*_ methods for IPython.
  • Add an optional feature for package installation.

Create Heating Unit

Summary

Provide a new Unit Class, maybe also a new unit base class for heating units like a Inductor or Conductor unit.

Detailed Description

Since more and more heating processes are transferred to the process route and are electrified we should include a inductor and conductor unit. This would be also needed for the ModiPlant project.

Unify behavior of plastic strain without or with transports

Summary

I consider the fact that PyRolL switches the way the plastic strain is treated based on the fact whether a transport is present or not a severe design flaw. Without transport plastic strain is accumulated with transport present it is reset to zero between stands.

As it seems to be an accepted assumption that for most materials recrystallization occurs between stands this should be the default PyRolL-behavior regardless whether transports are present.

It should be possible for the user to request accumulative plastic strain via a PyRolL-setting.

Provide a profile-type hexagon

Summary

In 3-roll processes sometimes in_profiles with a hexagonal cross-section a used.
PyRolL should provide a respective profile-type

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.