{ "info": { "author": "Kim G L Pedersen", "author_email": "georglind@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "# konvert\n\nKonvert implements universal conversion graphs for e.g. coordinate transformations.\n\nAt the core, konvert represents types connected by conversions on a graph. Such conversion graphs can be expandend incrementally, because it only requires two connections to connect a new type to the graph, This type can then be freely converted to any other type in the graph, by automatically chaining conversions between existing types.\n\nThe automatic chaining requires the conversions to be parameter-free. Conversions with additional parameters are called projections, which konvert also helps you manage.\n\n## Points\n\nThe moule konvert.points includes a conversion graph for coordinate transformations. As an example consider a set of points in two-dimensional Cartesian coordinates:\n\n```python\nfrom konvert.points import Cartesian2D\n\nline = Cartesian2D(x=[0, 1, 2], y=[0, 1, 2])\n```\n\nThis points can be converted to other implented 2D point sets, like ``Polar`` and ``Bipolar``, by using the ``to()`` method\n\n```python\nfrom konvert.points import Polar, Bipolar\n\nlp = line.to(Polar)\nlb = line.to(Bipolar)\n```\n\nIt can also be lifted up to its 3D description, ```l3 = line.to(Cartesian3D)```. The conversion graph can automatically chain conversions, so in fact, any point in the plane can be hoisted up to any point in three-dimensional space. That means, that points in e.g. polar coordinates, can be hoisted up to ```Cartesian3D```.\n\n```python\np0 = Polar(theta=30 * degrees, r=1.5).to(Cartesian3D)\n```\n\nPoints in 3D can be represented using the coordinate representations ``Cartesian3D``, ``Cylindrical``, and ``Spherical``. All Cartesian types have some helper methods for easily manipulating points. \n\n```python\np0 = Cartesian3D(1, 1, 1)\nq0 = Cartesian3D(1, 1, 0)\n\n# Create normalized version\np1 = p0.normalized()\n\n# Shift p0 by q0\np0.shift(q0) \n\n# Rotate around an axis thorugh q0.\np0.rotate(theta=45 * degrees, point=q0)\n```\n\n### Helpers\n\nBecause the points module work extensively with angles, konvert defines a convenience ``degrees`` symbol, which converts values and arrays in degrees to radians,\n\n```python\nfrom konvert.points import degrees\n\ntheta = 90 * degrees\n# theta is now pi/2\n\ntheta = numpy.array([45, 60, 90, 180, 360]) * degrees\n# theta is now numpy.array([pi/4, pi/3, pi/2, pi, 2*pi])\n```\n\n### Map projections\n\nThe points module also contains a set of map projections: ``Azimuthal``, ``AzimuthalEquidistant``, ``Mercator``, ``Orthographic``, ``Stereographic`` and ``Equirectangular``. Points are represented on the ``Sphere``, in spherical coordinates, or in ``Equitorial`` coordinates (lattitude and longitude).\n\n```python\npoints = Equitorial([40.12, 50.53] * degrees, [33.16, 44.53] * degrees, r=1)\n\np0 = points.project(Mercator)\np1 = points.project(Stereographic)\n...\n```\n\nThe points can be easily plotted using matplotlib and the plot utility on Cartesian2D, ``p0.to(Cartesian2D).plot()``.\n\n### Extending the conversion graph\n\nIt is fairly simple to extend an existing conversion graph and an existing projection collection. Let us extend the points graph with a Skew2D coordinate system. Note the use of numpy to efficiently represent and transform coordinates.\n\n```python\nimport numpy\nfrom konvert.points import Points\n\nclass Skew2D(Points):\n _sig = ('x', 'y', 'theta')\n\n def __init__(self, x, y, theta):\n \"\"\" \n Skew 2D coordinates. Theta is a scalar denominating the skew angle.\n \"\"\"\n self.x = numpy.array(x)\n self.y = numpy.array(y)\n self.theta = theta\n```\n\nThe Skew2D class can be connected to the ``konvert.points`` conversion graph by using the following conversion.\n\n```python\nfrom konvert.points import converters, Conversion\n\n@converters.register()\nclass Skew2DToCartesian2D(Conversion):\n src = Skew2D\n dst = points.Cartesian2D\n\n @staticmethod\n def convert(skew):\n return points.Cartesian2D(skew.x + numpy.cos(theta) * skew.y, numpy.sin(theta) * skew.y)\n```\n\nThe reverse conversion requires the additional theta parameter and must be implemented as a projection.\n\n```python\nfrom konvert.points import projectors, Projection\n\n@projectors.register()\nclass Cartesian2DToSkew2D(Projection):\n src = points.Cartesian2D\n dst = Skew2D\n\n @staticmethod\n def project(cart, theta=np.pi / 2):\n y = cart.y / numpy.sin(theta)\n x = cart.x - numpy.cos(theta) * y\n return Skew2D(x, y, theta)\n```\n\nWith these two additions we can convet between Skew2D points and any points type in the graph,\n\n```python\np0 = Skew2D(1, 2, theta=45 * degrees)\np1 = p0.to(Cylindrical)\n```\n\nor the opposite way,\n\n```python\np1 = Cylindrical(theta=30 * degrees, phi=45 * degrees, r=10)\np0 = p1.project(OnPlane).project(Cartesian2DToSkew2D, theta=45 * degrees)\n```\n\n## Extensions \n\nThe conversion graph has been implemented in the ``conversions`` module. It is possible to create additional conversion graphs and register existing or new conversions in those graphs. As an example we may create a colors module, which converts between values in the RGB and HSL color space. For this is example we will not bother with vectorizing the entities, and instead just work with single color entries and use the ``colorsys`` module in the python standard library.\n\n```python\nimport colorsys\nfrom konvert.conversions import Conversion, ConversionGraph\n\nconverters = ConversionGraph()\n\nclass Color(metaclass=ABCMeta): \n def to(self, type):\n return convertes.convert(self, type)\n\n\nclass RGB(Color):\n def __init__(self, r, g, b):\n self.r = r\n self.g = g\n self.b = b\n\nclass HSL(Color):\n def __init__(self, h, s, l):\n self.h = h\n self.s = s\n self.l = l\n\nconverters.register()\nclass RGBToHSL(Conversion):\n src = RGB\n dst = HSL\n\n @staticmethod\n def convert(rgb):\n hsl = colorsys.rgb_to_hsl(rgb.r, rgb.g, rgb.b)\n return HSL(*hsl)\n\n\nconverters.register()\nclass HSLToRGB(Conversion):\n src = RGB\n dst = HSL\n\n @staticmethod\n def convert(hsl):\n rgb = colorsys.hsl_to_rgb(hsl.h, hsl.s, hsl.l)\n return RGB(*rgb)\n```\n\nWe can now write ``RGB(0.1, 0.3, 0.3).to(HSL)`` and get the correct result.\n\nIf we wanted, we could merge this graph into the points conversion graph, or include part of the points graph in the color conversion graph... \n\n\n\n\n\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/georglind/konvert", "keywords": "", "license": "ASL 2.0", "maintainer": "", "maintainer_email": "", "name": "konvert", "package_url": "https://pypi.org/project/konvert/", "platform": "", "project_url": "https://pypi.org/project/konvert/", "project_urls": { "Homepage": "https://github.com/georglind/konvert" }, "release_url": "https://pypi.org/project/konvert/0.1.0/", "requires_dist": [ "numpy", "matplotlib ; extra == 'plotting'" ], "requires_python": ">=3.6.0", "summary": "Build graphs of types connected by conversions and projections", "version": "0.1.0" }, "last_serial": 5499777, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "25c392b8ecf5a45a5ac7cbab8c9ebd32", "sha256": "1c19f54c658f280a2c6135694cb48ad3ce4f8720a7e0f16b0e17ad86e209b532" }, "downloads": -1, "filename": "konvert-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "25c392b8ecf5a45a5ac7cbab8c9ebd32", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 13826, "upload_time": "2019-07-08T09:29:38", "url": "https://files.pythonhosted.org/packages/75/b4/e0b97ac2875170ed8548ce0d503f5c463bac23a8fdf82d1c393dfc671765/konvert-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "26a3209dabb248cf95a77d814b0888fb", "sha256": "5498ebb5e47b56ef0d473029a4012c8d49f4bb1fd6dccac12a6234b5eda149a7" }, "downloads": -1, "filename": "konvert-0.1.0.tar.gz", "has_sig": false, "md5_digest": "26a3209dabb248cf95a77d814b0888fb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 12743, "upload_time": "2019-07-08T09:29:40", "url": "https://files.pythonhosted.org/packages/fb/77/dfde7163ed524a42a79048ad1283df8780ceeddace1a63adf21e70ed695c/konvert-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "25c392b8ecf5a45a5ac7cbab8c9ebd32", "sha256": "1c19f54c658f280a2c6135694cb48ad3ce4f8720a7e0f16b0e17ad86e209b532" }, "downloads": -1, "filename": "konvert-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "25c392b8ecf5a45a5ac7cbab8c9ebd32", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 13826, "upload_time": "2019-07-08T09:29:38", "url": "https://files.pythonhosted.org/packages/75/b4/e0b97ac2875170ed8548ce0d503f5c463bac23a8fdf82d1c393dfc671765/konvert-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "26a3209dabb248cf95a77d814b0888fb", "sha256": "5498ebb5e47b56ef0d473029a4012c8d49f4bb1fd6dccac12a6234b5eda149a7" }, "downloads": -1, "filename": "konvert-0.1.0.tar.gz", "has_sig": false, "md5_digest": "26a3209dabb248cf95a77d814b0888fb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 12743, "upload_time": "2019-07-08T09:29:40", "url": "https://files.pythonhosted.org/packages/fb/77/dfde7163ed524a42a79048ad1283df8780ceeddace1a63adf21e70ed695c/konvert-0.1.0.tar.gz" } ] }