chalk-diagrams / chalk Goto Github PK
View Code? Open in Web Editor NEWA declarative drawing API in Python
License: MIT License
A declarative drawing API in Python
License: MIT License
Following the spirit of the Diagrams API this will add named/withName functions that will allow the user to get the transformed location of named elements to draw connections.
Adding __version__
will allow checking version with chalk.__version__
.
Simplify Makefile.
The Makefile has a few problems, and also it is not well documented and well organized. If properly worked on, it could simplify a lot of steps.
.PHONY
declarations are either nonexistent or the commands that should have been updated, are not there.make
commands with variables could lead to lesser human-error. This will require some reorganization.make
commands that can directly run several steps such as flake
, black
, type
, clean
, etc.interrogate
to the workflow. For now set the requirement at 0%
to pass interrogate
runs.
The current .gitignore
lacks many of the standard python ignore rules. Please update this with a standard .gitignore
(typically autogenerated by GitHub) and add any additional user-defined rules.
Add GitHub actions workflow selfassign
.
#self-assign
on any open-issue in this repository.Docs are broken again. I need to add them to the CI so I don't keep breaking them.
Adding a docs website with MkDocs framework could yield very pretty results. Also, maintaining MkDocs documentation website takes minimal effort.
Replace a bunch of the placeholders in the docs with more descriptive string.
I don't know if this would improve the visuals of the arrows, but I was wondering whether it would help to emulate the behaviour of connectOutside
from diagrams
(but using bounding boxes instead of traces):
The arrow lies on the line between the centres of the diagrams, but is drawn so that it stops at the boundaries of the diagrams
Ideally, I would like to be able to draw something like this
but without manually specifying the "cardinal" points of each arrow.
@srush What do you think? Is it worth investing time in something like this?
As suggested in this comment from #78, it would be useful to allow for curves in Trail
s and Path
s. It might be also a good opportunity to add BΓ©zier curves (or splines, as discussed in #35) as a primitive for the curvy segments; as always we can draw inspiration from diagrams
βsee their implementation of Segment
.
Haskell's diagrams
allows for multiple interpretations of the domain specific language (DSL). For example, the code
mconcat . iterateN 3 (rotateBy (1/9)) $ triangle 1
can yield various outputs depending on how it is interpreted: the image on left, if interpreted as a diagram, or the third image, if interpreted as a trail.
(See their manual for more information.)
This feature might be nice to have (it will allow drawing something like the Hilbert curve), but I expect to be rather involved.
I looked at a couple of Geometry libraries today to see if we could pull that part out of chalk. My conclusion is that the best one to use would be Planar
. https://pythonhosted.org/planar/
It's a weird choice, because it is unsupported, and hasn't been updated since 2011. However, I found it because it is where our Affine
class comes from which I really like.
Benefits of Planar:
Downsides:
@danoneata when you get a chance can you turn on the github pages gh-pages
branch in the settings.
Think this one is not so hard. But I need it for my diagrams.
The file MANIFEST.in
is used to specify inclusion/exlcusion of files/folders in the source package. Adding it ensures unambiguous inclusion or exlcusion of specific files and folders from the repository.
Add docstring to all the methods under chalk.bounding_box.BoundingBox
.
import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.bounding_box.BoundingBox) if not e.startswith("_")]))
The methods of chalk.core.Diagram:
apply_transform()
bl()
bottom()
cardinal()
center()
empty()
enclose()
from_limits()
height()
left()
reflect_x()
reflect_y()
right()
rotate()
rotate_by()
scale()
scale_x()
scale_y()
shear_x()
shear_y()
top()
tr()
translate()
translate_by()
union()
width()
Following diagrams
plan is to use "normalized" units for setting line_widths and arrow sizes.
The way this works is that there will be two commands line_width_local
and line_width
. The first will scale with the transformations applied to it, and the second will be a scale_invariant, but will be a fraction of the final document size.
This is implemented for the SVG backend using the vector-effect
command. For PNG and PDF need to think through the best way to do it.
I think this is pretty straightforward. Just need to upload to the chalk repo name.
Add docstring to all the methods under chalk.core.Diagram
.
import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.core.Diagram) if not e.startswith("_")]))
The methods of chalk.core.Diagram:
Legend: π Not Applicable
above()
above2()
align_b()
align_bl()
align_br()
align_l()
align_r()
align_t()
align_tl()
align_tr()
apply_transform()
at_center()
atop()
beside()
center_xy()
dashing()
display()
fill_color()
fill_opacity()
get_bounding_box()
get_subdiagram_bounding_box()
π line_color()
line_width()
named()
pad()
pad_b()
pad_l()
pad_r()
pad_t()
reflect_x()
reflect_y()
render()
render_svg()
rotate()
rotate_by()
scale()
scale_uniform_to_x()
scale_uniform_to_y()
scale_x()
scale_y()
shear_x()
shear_y()
show_bounding_box()
show_origin()
to_list()
to_svg()
π translate()
translate_by()
Make it clear what is public and what is private on the website.
For the placement of the nodes, it might be useful to have a counterpart of the functions position
or atPoints
from diagrams
. These would allow to place node elements at a given location based on a list of coordinates or the points from a given diagram:
nodes = [circle(0.3) + text(str(i), 0.2) for i in range(6)]
diagram = place_at_points(regular_polygon(6, 1).as_points(), nodes)
# or alternatively
diagram = regular_polygon(6, 1).place(nodes)
Doing the effective placement should be straightforward; the harder bit is to to get the "points" of a diagram.
This will help with type hinting.
Add an empty file at the path: chalk/py.typed
.
One thing I have been needing a lot is right-headed version of composition. I am not sure of the language for this in terms of monoids, but I want it to be like :
d1 / d2 where the origin stays at d2 instead of moving to d1.
I was thinking of notating this like
d1 // d2
, but maybe that is confusing. I guess the alternative would be to have a left facing below
operator d2 \ d1
if that is possible in python.
Any thoughts.
Add a dev_requirements.txt
file:
black
flake8
mypy
interrogate
(necessary for #41)π₯ This WILL NOT be source-tracked.
Lo-pri: The Haskell cubic spline api seems pretty doable now that we have paths / trails. I think this could be implemented as a Spline shape that takes a path and renders it using https://docs.scipy.org/doc/scipy/tutorial/interpolate.html
https://hackage.haskell.org/package/diagrams-lib-1.4.5.1/docs/Diagrams-CubicSpline.html#g:1
Downside is this brings in a scipy dependency and is maybe not that important a feature.
The Cairo API is really nice, but it is a pain to install in many contexts. When working in a notebook, the SVG backend seems fine and has minimal dependencies.
Proposal:
This code
circle(1).fill_color(papaya).fill_color(black)
generates a black circle when rendered as PNG and a papaya one when rendered as SVG. The expected behaviour should be the former. The generated SVG code seems correct:
<g style="fill: #000000;"><g style="fill: #ff9700;"><g style=";" transform="scale(1)"><circle cx="0" cy="0" r="1" /></g></g></g>
Should we resolve the styling prior to rendering? Or is there a simpler solution?
Convert examples to be in literate format such as https://jupytext.readthedocs.io/en/latest/formats.html#the-light-format and commit rendered Ipynb notebooks.
For text bounding boxes we are reliant on calling PyCairo TextExtents. As far as I can tell this function call is just broken, or something else is going wrong:
One solution is that if we know the exact font there are ways of calculating sizes. However this might rely on having a font distributed with the library.
Update Diagram to let users define a default render_size.
Something like:
d.render_size(height=100)
Connectors need curves to look good.
Not sure how to do this. I like the "bend right" / "bend left" in tikz, but maybe Diagrams has a better API.
I would really like to never have to write TikZ again. Looking at the PGF API it seems similar to Cairo, and we could draw to it. Diagrams has a PGF backend, but it does look like it needs to setup a connection to a PGF server of some sort to measure font sizes.
It seems like planar relies on a conversion library 'build_py_2to3' that is deprecated in the latest versions of distutils. This is a note to myself to fix this.
I think the best way to do this may be to just host a modern version of this code. My fault for using an old library.
I try to run command pip install git+https://github.com/danoneata/chalk@srush-patch-1, But an error occurred:
Γ python setup.py egg_info did not run successfully.
β exit code: 1
β°β> [13 lines of output]
Traceback (most recent call last):
File "/tmp/pip-install-ofq9w8yg/planar_3384c07b07cb49e694e3d9f59655d633/setup.py", line 11, in
from distutils.command.build_py import build_py_2to3 as build_py
ImportError: cannot import name 'build_py_2to3' from 'distutils.command.build_py' (/home/steve/.conda/envs/py37/lib/python3.7/site-packages/setuptools/_distutils/command/build_py.py)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 36, in <module>
File "<pip-setuptools-caller>", line 34, in <module>
File "/tmp/pip-install-ofq9w8yg/planar_3384c07b07cb49e694e3d9f59655d633/setup.py", line 14, in <module>
raise ImportError("build_py_2to3 not found in distutils - it is required for Python 3.x")
ImportError: build_py_2to3 not found in distutils - it is required for Python 3.x
[end of output]
And my python version is totally the same with Colab.
sys.version
'3.7.13 (default, Mar 29 2022, 02:18:16) \n[GCC 7.5.0]'
Adding a display method to chalk.core.Diagram
object could be very helpful in visualizing the diagram, without having to save it on disk.
The chalk.utils.imgen()
function will be used here.
Please add a LICENSE
file in the repository as well as in the PyPI source.
π I am working on adding chalk-diagrams
to conda-forge. A license file is necessary in the PyPI source. Here's the PR.
β‘ Once the library is added to conda-forge, it could be installed with conda
.
conda install -c conda-forge chalk-diagrams
Cairo is really powerful in that it let's you export to a lot of backends, but there are some cases when just SVG would be simpler and allow for more features. For example arrow heads are trivial in SVG and basically impossible in Cairo.
The plan is to include a render_svg
function on shapes / style, using svgwrite
. Since SVG is heirarchical this also means to_list is not necessary for this backend.
Notes on Envelopes from reading Pearl.
Questions:
There is a typo: black
is being called instead of isort
.
Give a way to sync multiple diagrams in a notebook to have the same relative widths.
Add docstring to all the classes other than Diagram
in chalk/core.py
.
Primitive
Empty
Compose
ApplyTransform
ApplyStyle
ApplyName
Note: chalk.core.Diagram
is already covered by issue #47
Add docstring to all the methods under chalk.point.Vector
.
import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.point.Vector) if not e.startswith("_")]))
The methods of chalk.point.Vector:
angle()
apply_transform()
from_polar()
length()
reflect_x()
reflect_y()
rotate()
rotate_by()
scale()
scale_x()
scale_y()
shear_x()
shear_y()
translate()
translate_by()
Plan is to follow the diagrams API with a image / Image
class. Use cairo to get a size estimate. In svg they will just be symbolically imported and in cairo they will be rendered in.
Currently setup.py
uses distutils
but the GitHub workflow installs setuptools.
Additionally, update various optional keyword parameters in setup()
function call to make the PyPI package publishing more informative.
find_packages()
from setuptools)pyproject.toml
to the repository root Add a new chalk.utils
module. This module will offer various diagram display utilities as follows.
utils.show(filepath: str)
:
Use this function for displaying saved images from disk.
utils.imgen(d: Diagram, **kwargs)
:
Use this function to display a diagram, without creating any permanent file on disk.
π This function does the following:
- Creates a temporary file.
- If necessary, it also creates a temporary folder for storing the temporary file.
- Displays the temporary-image-file for a user-specified (optional)
5
seconds.- Clears up both the temporary file and folder after the 5 seconds have elapsed.
utils.quick_probe(**kwargs)
:
Use this function to quickly generate a default sample Diagram (or a user-provided Diagram) and display it without saving it.
I believe, with these utilities it will be quite easy to visualize diagrams without having to save them on the disk.
Add docstring to all the methods under chalk.point.Point
.
import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.point.Point) if not e.startswith("_")]))
The methods of chalk.point.Point:
apply_transform()
reflect_x()
reflect_y()
rotate()
rotate_by()
scale()
scale_x()
scale_y()
shear_x()
shear_y()
translate()
translate_by()
Add docstring to all the methods under chalk.trail.Trail
.
import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.trail.Trail) if not e.startswith("_")]))
The methods of chalk.trail.Trail:
apply_transform()
from_path()
reflect_x()
reflect_y()
rotate()
rotate_by()
scale()
scale_x()
scale_y()
shear_x()
shear_y()
stroke()
to_path()
transform()
translate()
translate_by()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.