konstantint / matplotlib-venn

Area-weighted venn-diagrams for Python/matplotlib
MIT License
512 stars 68 forks source link

Regarding of the previous issue I posted: Issue #44 #45

Closed felixlee0530 closed 4 years ago

felixlee0530 commented 4 years ago

https://github.com/konstantint/matplotlib-venn/issues/44#issuecomment-579228349 Regarding of the reply you posted in Issue #44,

What do you mean about the external user input?

Based on your reply, is it possible for me to produce an algorithm using asteval or pyparsing to convert a written formula to the output of the Venn diagram without creating a list of corresponding formulas and outputs? Or, am I necessary to create a list of the inputs to use either of the Python packages you mentioned above? I was not sure about this when I read your reply. Hopefully there is a Python package which I can convert a written formula to lists of Venn diagram sectors which should be shaded, (like the example I showed in Issue #44) but if it's not possible, then I may need to make a huge list of inputted formulas, which is unstable and also buggy.

Also, if a directly-converting algorithm is possible with either asteval or pyparsing, could you please reply with a brief example so that I can get some understanding of how to create my code?

Please don't directly close the issue as you would not receive any notifications anymore. I am kinda a beginner to this area and your help will be truly appreciated. If you have one, could you please actually link your email/discord account so that I may further ask you if I am completely stuck for something? I will try to create the code independently as possible, but I may meet huge barriers.

Thanks a lot.

konstantint commented 4 years ago

Note that you do not have to create a new issue every time - it would make more sense to continue the comment thread in the previous one. Closing an issue does not turn off notifications, as far as I know.

The remark about external user input was related to the use of eval() in my example. If you are making an application where users are allowed to input the formula, passing it to eval() would allow any user to execute arbitrary Python code just as well. Whether this is a problem or not depends on your situation.

Anyway, try installing the asteval package and replacing the call to eval(formula, ..., dict(...)) in the example I provided with asteval.Interpreter(dict(...)).eval(formula). This should result in the code that would be safer to external exploits (although I'm not sure how much safer). Refer to the docs for more information.

I am not sure I might have much time for hand-holding a complete beginner through a programming project at the moment, but if you get really stuck, feel free to keep asking in this thread then.

felixlee0530 commented 4 years ago

Note that you do not have to create a new issue every time - it would make more sense to continue the comment thread in the previous one. Closing an issue does not turn off notifications, as far as I know.

The remark about external user input was related to the use of eval() in my example. If you are making an application where users are allowed to input the formula, passing it to eval() would allow any user to execute arbitrary Python code just as well. Whether this is a problem or not depends on your situation.

Anyway, try installing the asteval package and replacing the call to eval(formula, ..., dict(...)) in the example I provided with asteval.Interpreter(dict(...)).eval(formula). This should result in the code that would be safer to external exploits (although I'm not sure how much safer). Refer to the docs for more information.

I am not sure I might have much time for hand-holding a complete beginner through a programming project at the moment, but if you get really stuck, feel free to keep asking in this thread then.

Thanks for your reply.

1. So, in order to construct the program, do you think the only way is to create a python file with the list of formulas <> outcomes, and linking that python database(?) file to the main program? I guess the one you explained in the previous reply and the reply above are related to linking my main program to the possible amount of lists that I can create.

2. The most curious thing is, are there any algorithms I can generate or Python libraries/packages that I can use to convert a simplified formula to a Venn diagram outcome? Like converting something like (A and B) or C to lists of sectors to be shaded in the diagram, without referencing to the lists of formulas <> outcomes. I hope there is a package which can convert those type of formulas to simpler outputs which I can link them to matplotlib-venn to shade the Venn diagram.

3. In order to create a 3-circled Venn diagram with a Universal set, I used the code below and it shows the following output:

plt.figure(figsize=(5, 5))
v = venn3(subsets=(1, 1, 1, 1, 1, 1, 1), set_labels=('A', 'B', 'C'))
for idx, subset in enumerate(v1.subset_labels):
    v.subset_labels[idx].set_visible(False)
c = venn3_circles(subsets=(1, 1, 1, 1, 1, 1, 1), linestyle='solid')
plt.title("THREE CIRCLE VENN DIAGRAM")
plt.axis('on')
plt.show(v)

Output: image Is there a possible method to shade/color the region outside of the two circles, which is the complement of A union B union C? Also, is it possible to label the Universal set U? image 4. How do I adjust horizontal/vertical positions of the set labels like (A/B/C/U) that I created?

Again, thanks a lot for your help.

konstantint commented 4 years ago
  1. No. Please revise my first answer to your question (the one from issue #44). I offered you example implementation for solving your problem without the need to store all possible formulas.

  2. Yes, such an algorithm would simply evaluate the given formula for every single region and output the regions where the formula evaluates to True. This is what list_regions in my answer to #44 does. Please, try reading, understanding and using that code before proceding any further.

  3. See #32.

  4. See #2.

felixlee0530 commented 4 years ago

Wow.. okay. I think I misunderstood your explanation in #44. I will try out your code using list_regions first and see if it works for me. So, is using pyparsing or asteval actually more efficient in terms of error handling?

Regarding of question 3, I tried looking at #32 of course before I asked you the question above. I created the function executeVenn3() which is shown below, to get the following output below: Code:

def executeVenn3():
    plt.figure(figsize=(5, 5))
    v1 = venn3(subsets=(1, 1, 1, 1, 1, 1, 1), set_labels=('A', 'B', 'C'))
    for idx, subset in enumerate(v1.subset_labels):
        v1.subset_labels[idx].set_visible(False)
    xa, ya = v1.get_label_by_id("A").get_position()
    v1.get_label_by_id("A").set_position((xa+0.15, ya-0.11))
    xb, yb = v1.get_label_by_id("B").get_position()
    v1.get_label_by_id("B").set_position((xb-0.15, yb-0.11))
    xc, yc = v1.get_label_by_id("C").get_position()
    v1.get_label_by_id("C").set_position((xc+0, yc+0.15))
    for text in v1.set_labels:
        text.set_fontsize(16)
        text.set_fontweight('bold')
    for i in range(7):
        v1.get_patch_by_id(convertBinary(i+1)).set_color("#FFFFFF")

    c1 = venn3_circles(subsets=(1, 1, 1, 1, 1, 1, 1), linestyle='solid')
    plt.title("THREE-CIRCLED VENN DIAGRAM")
    top, bottom = plt.gca().get_xlim()[-1], plt.gca().get_ylim()[-1]
    plt.annotate("U", (top, bottom))
    plt.axis('on')
    plt.show(v1)

Output: image

However, in terms of this, I am stuck on two options:

konstantint commented 4 years ago

So, is using pyparsing or asteval actually more efficient in terms of error handling?

Python's eval function allows to execute nearly arbitrary Python code. ASTeval limits the possibility to mostly only arithmetic expressions. Pyparsing lets you define your own grammar. Please, do read the documentation for the libraries. If you feel overwhelmed, just use the eval version I provided to you, but make sure you do not deploy this code for public use (which I suspect you are not planning to do anyway)

I cannot find an option to shade the area

Simply color the whole rectangle via set_(face)color. Make sure it is drawn below the circles using set_zorder.

tried changing font size but it doesn't work

Simply providing fontsize argument to the annotate call should do the job. The documentation is here

felixlee0530 commented 4 years ago

I made the font size to work. Thanks. Could you please briefly give an example for what you mean here? (linked to my code)

Simply color the whole rectangle via set_(face)color. Make sure it is drawn below the circles using set_zorder.

I simply used plt.axis('on') to plot the rectangle.

konstantint commented 4 years ago

http://tiny.cc/sincjz

felixlee0530 commented 4 years ago

Ok. I managed to write the functions off and now the program works totally fine in terms of functions. Thanks for your help!