avichr commited on
Commit
b6f956e
1 Parent(s): 91936fe

Delete pyplutchik

Browse files
Files changed (1) hide show
  1. pyplutchik +0 -1336
pyplutchik DELETED
@@ -1,1336 +0,0 @@
1
-
2
- """
3
- **********
4
- Plutchik
5
- **********
6
-
7
- This package contains a data visualization tool for corpora annotated with emotions.
8
- Given a JSON representation of the Plutchik's emotions (or dyads) in a text or in a group of texts,
9
- it draws the corresponding Plutchik's flower.
10
-
11
- See Plutchik, Robert. "A general psychoevolutionary theory of emotion." Theories of emotion. Academic press, 1980. 3-33.
12
-
13
- --------
14
- repository available at https://www.github.com/alfonsosemeraro/pyplutchik
15
- @author: Alfonso Semeraro <alfonso.semeraro@gmail.com>
16
-
17
- """
18
-
19
- import shapely.geometry as sg
20
- import matplotlib.pyplot as plt
21
- import descartes
22
- from math import sqrt, cos, sin, radians
23
- import numpy as np
24
- from matplotlib import colors
25
-
26
-
27
- __author__ = """Alfonso Semeraro (alfonso.semeraro@gmail.com)"""
28
- __all__ = ['emo_params',
29
- 'dyad_params',
30
- '_rotate_point',
31
- '_polar_coordinates',
32
- '_neutral_central_circle',
33
- '_petal_shape_emotion',
34
- '_petal_shape_dyad',
35
- '_petal_spine_emotion',
36
- '_petal_spine_dyad',
37
- '_petal_circle',
38
- '_draw_emotion_petal',
39
- '_draw_dyad_petal',
40
- '_check_scores_kind',
41
- 'plutchik']
42
-
43
-
44
-
45
-
46
- def emo_params(emotion):
47
- """
48
- Gets color and angle for drawing a petal.
49
- Color and angle depend on the emotion name.
50
-
51
- Required arguments:
52
- ----------
53
- *emotion*:
54
- Emotion's name. Possible values:
55
- ['joy', 'trust', 'fear', 'surprise', 'sadness', 'disgust', 'anger', 'anticipation']
56
-
57
-
58
- Returns:
59
- ----------
60
- *color*:
61
- Matplotlib color for the petal. See: https://matplotlib.org/3.1.0/gallery/color/named_colors.html
62
-
63
- *angle*:
64
- Each subsequent petal is rotated 45° around the origin.
65
-
66
-
67
- Notes:
68
- -----
69
- This function allows also 8 principal emotions, one for each Plutchik's flower petal.
70
- No high or low intensity emotions are allowed (no 'ecstasy' or 'serenity', for instance).
71
- """
72
-
73
- if emotion == 'joy':
74
- color = 'gold'
75
- angle = 0
76
- elif emotion == 'trust':
77
- color = 'olivedrab'
78
- angle = -45
79
- elif emotion == 'fear':
80
- color = 'forestgreen'
81
- angle = -90
82
- elif emotion == 'surprise':
83
- color = 'skyblue'
84
- angle = -135
85
- elif emotion == 'sadness':
86
- color = 'dodgerblue'
87
- angle = -180
88
- elif emotion == 'disgust':
89
- color = 'slateblue'
90
- angle = -225
91
- elif emotion == 'anger':
92
- color = 'orangered'
93
- angle = -270
94
- elif emotion == 'anticipation':
95
- color = 'darkorange'
96
- angle = -315
97
- else:
98
- raise Exception("""Bad input: {} is not an accepted emotion.
99
- Must be one of 'joy', 'trust', 'fear', 'surprise', 'sadness', 'disgust', 'anger', 'anticipation'""".format(emotion))
100
- return color, angle, 0
101
-
102
-
103
-
104
-
105
-
106
- def dyad_params(dyad):
107
- """
108
- Gets colormap and angle for drawing a dyad.
109
- Colormap and angle depend on the dyad name.
110
-
111
- Required arguments:
112
- ----------
113
- *dyad*:
114
- Dyad's name. Possible values:
115
-
116
- {"primary": ['love', 'submission', 'alarm', 'disappointment', 'remorse', 'contempt', 'aggression', 'optimism'],
117
- "secondary": ['guilt', 'curiosity', 'despair', '', 'envy', 'cynism', 'pride', 'fatalism'],
118
- "tertiary": ['delight', 'sentimentality', 'shame', 'outrage', 'pessimism', 'morbidness', 'dominance', 'anxiety']}
119
-
120
- Returns:
121
- ----------
122
- *colormap*:
123
- Matplotlib colormap for the dyad. See: https://matplotlib.org/3.1.0/gallery/color/named_colors.html
124
-
125
- *angle*:
126
- Each subsequent dyad is rotated 45° around the origin.
127
-
128
-
129
- """
130
-
131
-
132
- # PRIMARY DYADS
133
- if dyad == 'love':
134
- cmap = ['gold', 'olivedrab']
135
- angle = -45 / 2
136
- emos = ['joy', 'trust']
137
- level = 1
138
-
139
- elif dyad == 'submission':
140
- cmap = ['olivedrab', 'forestgreen']
141
- angle = (-45 / 2) + (-45)
142
- emos = ['trust', 'fear']
143
- level = 1
144
-
145
- elif dyad == 'alarm':
146
- cmap = ['forestgreen', 'skyblue']
147
- angle = (-45 / 2) + (-90)
148
- emos = ['fear', 'surprise']
149
- level = 1
150
-
151
- elif dyad == 'disappointment':
152
- cmap = ['skyblue', 'dodgerblue']
153
- angle = (-45 / 2) + (-135)
154
- emos = ['surprise', 'sadness']
155
- level = 1
156
-
157
- elif dyad == 'remorse':
158
- cmap = ['dodgerblue', 'slateblue']
159
- angle = (-45 / 2) + (-180)
160
- emos = ['sadness', 'disgust']
161
- level = 1
162
-
163
- elif dyad == 'contempt':
164
- cmap = ['slateblue', 'orangered']
165
- angle = (-45 / 2) + (-225)
166
- emos = ['disgust', 'anger']
167
- level = 1
168
-
169
- elif dyad == 'aggressiveness':
170
- cmap = ['orangered', 'darkorange']
171
- angle = (-45 / 2) + (-270)
172
- emos = ['anger', 'anticipation']
173
- level = 1
174
-
175
- elif dyad == 'optimism':
176
- cmap = ['darkorange', 'gold']
177
- angle = (-45 / 2) + (-315)
178
- emos = ['anticipation', 'joy']
179
- level = 1
180
-
181
-
182
- # SECONDARY DYADS
183
- elif dyad == 'guilt':
184
- cmap = ['gold', 'forestgreen']
185
- angle = -45
186
- emos = ['joy', 'fear']
187
- level = 2
188
-
189
- elif dyad == 'curiosity':
190
- cmap = ['olivedrab', 'skyblue']
191
- angle = -90
192
- emos = ['trust', 'surprise']
193
- level = 2
194
-
195
- elif dyad == 'despair':
196
- cmap = ['forestgreen', 'dodgerblue']
197
- angle = -135
198
- emos = ['fear', 'sadness']
199
- level = 2
200
-
201
- elif dyad == 'unbelief':
202
- cmap = ['skyblue', 'slateblue']
203
- angle = -180
204
- emos = ['surprise', 'disgust']
205
- level = 2
206
-
207
- elif dyad == 'envy':
208
- cmap = ['dodgerblue', 'orangered']
209
- angle = -225
210
- emos = ['sadness', 'anger']
211
- level = 2
212
-
213
- elif dyad == 'cynism':
214
- cmap = ['slateblue', 'darkorange']
215
- angle = -270
216
- emos = ['disgust', 'anticipation']
217
- level = 2
218
-
219
- elif dyad == 'pride':
220
- cmap = ['orangered', 'gold']
221
- angle = -315
222
- emos = ['anger', 'joy']
223
- level = 2
224
-
225
- elif dyad == 'hope':
226
- cmap = ['darkorange', 'olivedrab']
227
- angle = 0
228
- emos = ['anticipation', 'trust']
229
- level = 2
230
-
231
- # TERTIARY DYADS
232
- elif dyad == 'delight':
233
- cmap = ['gold', 'skyblue']
234
- angle = (-45 / 2) + (-45)
235
- emos = ['joy', 'surprise']
236
- level = 3
237
-
238
- elif dyad == 'sentimentality':
239
- cmap = ['olivedrab', 'dodgerblue']
240
- angle = (-45 / 2) + (-90)
241
- emos = ['trust', 'sadness']
242
- level = 3
243
-
244
- elif dyad == 'shame':
245
- cmap = ['forestgreen', 'slateblue']
246
- angle = (-45 / 2) + (-135)
247
- emos = ['fear', 'disgust']
248
- level = 3
249
-
250
- elif dyad == 'outrage':
251
- cmap = ['skyblue', 'orangered']
252
- angle = (-45 / 2) + (-180)
253
- emos = ['surprise', 'anger']
254
- level = 3
255
-
256
- elif dyad == 'pessimism':
257
- cmap = ['dodgerblue', 'darkorange']
258
- angle = (-45 / 2) + (-225)
259
- emos = ['sadness', 'anticipation']
260
- level = 3
261
-
262
- elif dyad == 'morbidness':
263
- cmap = ['slateblue', 'gold']
264
- angle = (-45 / 2) + (-270)
265
- emos = ['disgust', 'joy']
266
- level = 3
267
-
268
- elif dyad == 'dominance':
269
- cmap = ['orangered', 'olivedrab']
270
- angle = (-45 / 2) + (-315)
271
- emos = ['anger', 'trust']
272
- level = 3
273
-
274
- elif dyad == 'anxiety':
275
- cmap = ['darkorange', 'forestgreen']
276
- angle = (-45 / 2)
277
- emos = ['anticipation', 'fear']
278
- level = 3
279
-
280
-
281
- # OPPOSITES
282
- elif dyad == 'bittersweetness':
283
- cmap = ['gold', 'dodgerblue']
284
- angle = 0
285
- emos = ['joy', 'sadness']
286
- level = 4
287
-
288
- elif dyad == 'ambivalence':
289
- cmap = ['olivedrab', 'slateblue']
290
- angle = -45
291
- emos = ['trust', 'disgust']
292
- level = 4
293
-
294
- elif dyad == 'frozenness':
295
- cmap = ['forestgreen', 'orangered']
296
- angle = -90
297
- emos = ['fear', 'anger']
298
- level = 4
299
-
300
- elif dyad == 'confusion':
301
- cmap = ['skyblue', 'darkorange']
302
- angle = -135
303
- emos = ['surprise', 'anticipation']
304
- level = 4
305
-
306
-
307
- else:
308
- raise Exception("""Bad input: '{}' is not an accepted name for a dyad.
309
- Must be one of:
310
- 'love', 'submission', 'alarm', 'disappointment', 'remorse', 'contempt', 'aggressiveness', 'optimism',
311
- 'guilt', 'curiosity', 'despair', 'unbelief', 'envy', 'cynism', 'pride', 'hope',
312
- 'delight', 'sentimentality', 'shame', 'outrage', 'pessimism', 'morbidness', 'dominance', 'anxiety',
313
- 'bittersweetness', 'ambivalence', 'frozenness', 'confusion'
314
- """.format(dyad))
315
- return emos, cmap, angle, level
316
-
317
-
318
- def _rotate_point(point, angle):
319
- """
320
- Rotate a point counterclockwise by a given angle around a given origin.
321
-
322
- Required arguments:
323
- ----------
324
- *point*:
325
- A two-values tuple, (x, y), of the point to rotate
326
-
327
- *angle*:
328
- The angle the point is rotated. The angle should be given in radians.
329
-
330
- Returns:
331
- ----------
332
- *(qx, qy)*:
333
- A two-values tuple, the new coordinates of the rotated point.
334
-
335
- """
336
- ox, oy = 0, 0
337
- px, py = point
338
- angle = radians(angle)
339
- qx = ox + cos(angle) * (px - ox) - sin(angle) * (py - oy)
340
- qy = oy + sin(angle) * (px - ox) + cos(angle) * (py - oy)
341
- return (qx, qy)
342
-
343
-
344
-
345
-
346
- def _polar_coordinates(ax, font, fontweight, fontsize, show_ticklabels, ticklabels_angle, ticklabels_size, offset = .15):
347
- """
348
- Draws polar coordinates as a background.
349
-
350
- Required arguments:
351
- ----------
352
- *ax*:
353
- Axes to draw the coordinates.
354
-
355
- *font*:
356
- Font of text. Default is Montserrat.
357
-
358
- *fontweight*:
359
- Font weight of text. Default is light.
360
-
361
- *fontsize*:
362
- Font size of text. Default is 15.
363
-
364
- *show_ticklabels*:
365
- Boolean, wether to show tick labels under Joy petal. Default is False.
366
-
367
- *ticklabels_angle*:
368
- How much to rotate tick labels from y=0. Value should be given in radians. Default is 0.
369
-
370
- *ticklabels_size*:
371
- Size of tick labels. Default is 11.
372
-
373
- *offset*:
374
- Central neutral circle has radius = .15, and coordinates must start from there.
375
-
376
- Returns:
377
- ----------
378
- *ax*:
379
- The input Axes modified.
380
-
381
- """
382
-
383
- # Lines
384
- for i in range(0, 110, 20):
385
- c = plt.Circle((0, 0), offset + i/100, color = 'grey', alpha = .3, fill = False, zorder = -20)
386
- ax.add_artist(c)
387
-
388
-
389
- # Tick labels
390
- if show_ticklabels:
391
- for x in np.arange(0.2, 1.2, .2):
392
- a = round(x, 1)
393
- x, y = _rotate_point((0, a + offset), ticklabels_angle) #-.12
394
- ax.annotate(s = str(a), xy = (x, y), fontfamily = font, size = ticklabels_size, fontweight = fontweight, zorder = 8, rotation = ticklabels_angle)
395
- return ax
396
-
397
-
398
- def _neutral_central_circle(ax, r = .15):
399
- """
400
- Draws central neutral circle (in grey).
401
-
402
- Required arguments:
403
- ----------
404
- *ax*:
405
- Axes to draw the coordinates.
406
-
407
- *r*:
408
- Radius of the circle. Default is .15.
409
-
410
- Returns:
411
- ----------
412
- *ax*:
413
- The input Axes modified.
414
-
415
- """
416
- c = sg.Point(0, 0).buffer(r)
417
- ax.add_patch(descartes.PolygonPatch(c, fc='white', ec=(.5, .5, .5, .3), alpha=1, zorder = 15))
418
-
419
- return ax
420
-
421
-
422
- def _outer_border(ax, emotion_score, color, angle, highlight, offset = .15, height_width_ratio = 1, normalize = False):
423
- """
424
- Draw a the outer border of a petal.
425
-
426
- Required arguments:
427
- ----------
428
- *ax*:
429
- Axes to draw the coordinates.
430
-
431
- *emotion_score*:
432
- Score of the emotion. Values range from 0 to 1.
433
-
434
- *color*:
435
- Color of the petal. See emo_params().
436
-
437
- *angle*:
438
- Rotation angle of the petal. See emo_params().
439
-
440
- *highlight*:
441
- String. 'opaque' if the petal must be shadowed, 'regular' is default.
442
-
443
- *offset*:
444
- Central neutral circle has radius = .15, and petals must start from there.
445
-
446
- *height_width_ratio*:
447
- Ratio between height and width of the petal. Lower the ratio, thicker the petal. Default is 1.
448
-
449
- *normalize*:
450
- Either False or the highest value among emotions. If not False, must normalize all petal lengths.
451
-
452
- """
453
-
454
- if normalize:
455
- emotion_score /= normalize
456
-
457
- # Computing proportions.
458
- h = 1*emotion_score + offset
459
- x = height_width_ratio*emotion_score
460
- y = h/2
461
- r = sqrt(x**2 + y**2)
462
-
463
- # Computing rotated centers
464
- x_right, y_right = _rotate_point((x, y), angle)
465
- x_left, y_left = _rotate_point((-x, y), angle)
466
-
467
- # Circles and intersection
468
- right = sg.Point(x_right, y_right).buffer(r)
469
- left = sg.Point(x_left, y_left).buffer(r)
470
- petal = right.intersection(left)
471
-
472
- # alpha and color
473
- alpha = 1 if highlight == 'regular' else .8
474
- ecol = (colors.to_rgba(color)[0], colors.to_rgba(color)[1], colors.to_rgba(color)[2], alpha)
475
-
476
-
477
- ax.add_patch(descartes.PolygonPatch(petal, fc=(0, 0, 0, 0), ec = ecol, lw= 1))
478
-
479
-
480
-
481
- def _petal_shape_emotion(ax, emotion_score, color, angle, font, fontweight, fontsize, highlight, will_circle, offset = .15, height_width_ratio = 1, normalize = False):
482
- """
483
- Draw a petal.
484
- A petal is the intersection area between two circles.
485
- The height of the petal depends on the radius and the center of the circles.
486
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
487
-
488
- Required arguments:
489
- ----------
490
- *ax*:
491
- Axes to draw the coordinates.
492
-
493
- *emotion_score*:
494
- Score of the emotion. Values range from 0 to 1.
495
-
496
- *color*:
497
- Color of the petal. See emo_params().
498
-
499
- *angle*:
500
- Rotation angle of the petal. See emo_params().
501
-
502
- *font*:
503
- Font of text. Default is Montserrat.
504
-
505
- *fontweight*:
506
- Font weight of text. Default is light.
507
-
508
- *fontsize*:
509
- Font size of text. Default is 15.
510
-
511
- *highlight*:
512
- String. 'opaque' if the petal must be shadowed, 'regular' is default.
513
-
514
- *will_circle*:
515
- Boolean. If three intensities will be plotted, then the lower petal must be pale.
516
-
517
- *offset*:
518
- Central neutral circle has radius = .15, and petals must start from there.
519
-
520
- *height_width_ratio*:
521
- Ratio between height and width of the petal. Lower the ratio, thicker the petal. Default is 1.
522
-
523
- *normalize*:
524
- Either False or the highest value among emotions. If not False, must normalize all petal lengths.
525
-
526
- Returns:
527
- ----------
528
- *petal*:
529
- The petal, a shapely shape.
530
-
531
- """
532
-
533
- if normalize:
534
- emotion_score /= normalize
535
-
536
- # Computing proportions.
537
- h = 1*emotion_score + offset
538
- x = height_width_ratio*emotion_score
539
- y = h/2
540
- r = sqrt(x**2 + y**2)
541
-
542
- # Computing rotated centers
543
- x_right, y_right = _rotate_point((x, y), angle)
544
- x_left, y_left = _rotate_point((-x, y), angle)
545
-
546
- # Circles and intersection
547
- right = sg.Point(x_right, y_right).buffer(r)
548
- left = sg.Point(x_left, y_left).buffer(r)
549
- petal = right.intersection(left)
550
-
551
- # Alpha for highlighting
552
- if highlight == 'regular':
553
- if will_circle:
554
- alpha = .3
555
- else:
556
- alpha = .5
557
-
558
- elif will_circle:
559
- alpha = .0
560
-
561
- else:
562
- alpha = .0
563
-
564
- ax.add_patch(descartes.PolygonPatch(petal, fc='white', lw = 0, alpha=1, zorder = 0))
565
- ax.add_patch(descartes.PolygonPatch(petal, fc=color, lw= 0, alpha=alpha, zorder = 10))
566
-
567
- return petal
568
-
569
-
570
- def _petal_shape_dyad(ax, emotion_score, colorA, colorB, angle, font, fontweight, fontsize, highlight, will_circle, offset = .15, height_width_ratio = 1, normalize = False):
571
- """
572
- Draw a petal.
573
- A petal is the intersection area between two circles.
574
- The height of the petal depends on the radius and the center of the circles.
575
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
576
-
577
- Required arguments:
578
- ----------
579
- *ax*:
580
- Axes to draw the coordinates.
581
-
582
- *emotion_score*:
583
- Score of the emotion. Values range from 0 to 1.
584
-
585
- *colorA*:
586
- First color of the petal. See dyad_params().
587
-
588
- *colorB*:
589
- Second color of the petal. See dyad_params().
590
-
591
- *angle*:
592
- Rotation angle of the petal. See dyad_params().
593
-
594
- *font*:
595
- Font of text. Default is Montserrat.
596
-
597
- *fontweight*:
598
- Font weight of text. Default is light.
599
-
600
- *fontsize*:
601
- Font size of text. Default is 15.
602
-
603
- *highlight*:
604
- String. 'opaque' if the petal must be shadowed, 'regular' is default.
605
-
606
- *will_circle*:
607
- Boolean. If three intensities will be plotted, then the lower petal must be pale.
608
-
609
- *offset*:
610
- Central neutral circle has radius = .15, and petals must start from there.
611
-
612
- *height_width_ratio*:
613
- Ratio between height and width of the petal. Lower the ratio, thicker the petal. Default is 1.
614
-
615
- *normalize*:
616
- Either False or the highest value among emotions. If not False, must normalize all petal lengths.
617
-
618
- Returns:
619
- ----------
620
- *petal*:
621
- The petal, a shapely shape.
622
-
623
- """
624
-
625
- if emotion_score == 0:
626
- return ax
627
-
628
- if normalize:
629
- emotion_score /= normalize
630
-
631
- # Computing proportions.
632
- h = 1*emotion_score + offset
633
- x = height_width_ratio*emotion_score
634
- y = h/2
635
- r = sqrt(x**2 + y**2)
636
-
637
- # Computing rotated centers
638
- x_right, y_right = _rotate_point((x, y), angle)
639
- x_left, y_left = _rotate_point((-x, y), angle)
640
-
641
- # Circles and intersection
642
- right = sg.Point(x_right, y_right).buffer(r)
643
- left = sg.Point(x_left, y_left).buffer(r)
644
- petal = right.intersection(left)
645
-
646
-
647
- # Computing squares: left
648
- A = _rotate_point((-2*x, 0), angle)
649
- B = _rotate_point((-2*x, h), angle)
650
- C = _rotate_point((0, h), angle)
651
- D = _rotate_point((0, 0), angle)
652
- square_left = sg.Polygon([A, B, C, D, A])
653
-
654
- # Computing squares: right
655
- A = _rotate_point((0, 0), angle)
656
- B = _rotate_point((0, h), angle)
657
- C = _rotate_point((2*x, h), angle)
658
- D = _rotate_point((2*x, 0), angle)
659
- square_right = sg.Polygon([A, B, C, D, A])
660
-
661
- # Computing semipetals
662
- petalA = petal.intersection(square_left)
663
- petalB = petal.intersection(square_right)
664
-
665
-
666
- # white petal underneath
667
- ax.add_patch(descartes.PolygonPatch(petal, fc='white', lw = 0, alpha=1, zorder = 0))
668
-
669
- # Draw each half-petal in alpha 0.7
670
- alpha = .7
671
-
672
- xs, ys = petalA.exterior.xy
673
- ax.fill(xs, ys, alpha=alpha, fc= colorA, ec='none')
674
-
675
- xs, ys = petalB.exterior.xy
676
- ax.fill(xs, ys, alpha=alpha, fc=colorB, ec='none')
677
-
678
- return ax
679
-
680
-
681
- def _petal_spine_emotion(ax, emotion, emotion_score, color, angle, font, fontweight, fontsize, highlight = 'all', offset = .15):
682
- """
683
- Draw the spine beneath a petal, and the annotation of emotion and emotion's value.
684
- The spine is a straight line from the center, of length 1.03.
685
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
686
-
687
- Required arguments:
688
- ----------
689
- *ax*:
690
- Axes to draw the coordinates.
691
-
692
- *emotion*:
693
- Emotion's name.
694
-
695
- *emotion_score*:
696
- Score of the emotion. Values range from 0 to 1. if list, it must contain 3 values that sum up to 1.
697
-
698
- *color*:
699
- Color of the petal. See emo_params().
700
-
701
- *angle*:
702
- Rotation angle of the petal. See emo_params().
703
-
704
- *font*:
705
- Font of text. Default is Montserrat.
706
-
707
- *fontweight*:
708
- Font weight of text. Default is light.
709
-
710
- *fontsize*:
711
- Font size of text. Default is 15.
712
-
713
- *highlight*:
714
- String. 'opaque' if the petal must be shadowed, 'regular' is default.
715
-
716
- *offset*:
717
- Central neutral circle has radius = .15, and petals must start from there.
718
-
719
- """
720
-
721
- # Diagonal lines and ticks
722
- step = .03
723
- p1 = (0, 0)
724
- p2 = _rotate_point((0, 1 + step + offset), angle) # draw line until 0, 1 + step + offset
725
- p3 = _rotate_point((-step, 1 + step + offset), angle) # draw tick
726
- ax.plot([p1[0], p2[0]], [p1[1], p2[1]], zorder = 5, color = 'black', alpha = .3, linewidth = .75)
727
- ax.plot([p2[0], p3[0]], [p2[1], p3[1]], zorder = 5, color = 'black', alpha = .3, linewidth = .75)
728
-
729
- # Managing highlighting and transparency
730
- if highlight == 'opaque':
731
- alpha = .8
732
- color = 'lightgrey'
733
- else:
734
- alpha = 1
735
-
736
- # Checking if iterable
737
- try:
738
- _ = emotion_score[0]
739
- iterable = True
740
- except:
741
- iterable = False
742
-
743
-
744
- if iterable:
745
- # Label
746
- angle2 = angle + 180 if -110 > angle > -260 else angle
747
- p4 = _rotate_point((0, 1.40 + step + offset), angle)
748
- ax.annotate(s = emotion, xy = p4, rotation = angle2, ha='center', va = 'center',
749
- fontfamily = font, size = fontsize, fontweight = fontweight)
750
-
751
- # Score 1
752
- p5 = _rotate_point((0, 1.07 + step + offset), angle)
753
- ax.annotate(s = "{0:.2f}".format(round(emotion_score[0],2)), xy = p5, rotation = angle2, ha='center', va = 'center',
754
- color = color, fontfamily = font, size = fontsize, fontweight = 'regular', alpha = alpha)
755
-
756
- # Score 2
757
- p6 = _rotate_point((0, 1.17 + step + offset), angle)
758
- ax.annotate(s = "{0:.2f}".format(round(emotion_score[1],2)), xy = p6, rotation = angle2, ha='center', va = 'center',
759
- color = color, fontfamily = font, size = fontsize, fontweight = 'demibold', alpha = alpha)
760
-
761
- # Score 3
762
- p7 = _rotate_point((0, 1.27 + step + offset), angle)
763
- ax.annotate(s = "{0:.2f}".format(round(emotion_score[2],2)), xy = p7, rotation = angle2, ha='center', va = 'center',
764
- color = color, fontfamily = font, size = fontsize, fontweight = 'regular', alpha = alpha)
765
-
766
- else:
767
- # Label
768
- angle2 = angle + 180 if -110 > angle > -260 else angle
769
- p4 = _rotate_point((0, 1.23 + step + offset), angle)
770
- ax.annotate(s = emotion, xy = p4, rotation = angle2, ha='center', va = 'center',
771
- fontfamily = font, size = fontsize, fontweight = fontweight)
772
-
773
- # Score
774
- p5 = _rotate_point((0, 1.1 + step + offset), angle)
775
- ax.annotate(s = "{0:.2f}".format(round(emotion_score,2)), xy = p5, rotation = angle2, ha='center', va = 'center',
776
- color = color, fontfamily = font, size = fontsize, fontweight = 'demibold', alpha = alpha)
777
-
778
-
779
-
780
- def _petal_spine_dyad(ax, dyad, dyad_score, color, emotion_names, angle, font, fontweight, fontsize, highlight = 'all', offset = .15):
781
- """
782
- Draw the spine beneath a petal, and the annotation of dyad and dyad's value.
783
- The spine is a straight line from the center, of length 1.03.
784
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
785
-
786
- Required arguments:
787
- ----------
788
- *ax*:
789
- Axes to draw the coordinates.
790
-
791
- *dyad*:
792
- Dyad's name.
793
-
794
- *dyad_score*:
795
- Score of the dyad. Values range from 0 to 1. if list, it must contain 3 values that sum up to 1.
796
-
797
- *color*:
798
- Color of the two emotions of the dyad. See dyad_params().
799
-
800
- *emotion_names*:
801
- Name of the emotions the dyad is made of. See dyad_params().
802
-
803
- *angle*:
804
- Rotation angle of the petal. See dyad_params().
805
-
806
- *font*:
807
- Font of text. Default is Montserrat.
808
-
809
- *fontweight*:
810
- Font weight of text. Default is light.
811
-
812
- *fontsize*:
813
- Font size of text. Default is 15.
814
-
815
- *highlight*:
816
- String. 'opaque' if the petal must be shadowed, 'regular' is default.
817
-
818
- *offset*:
819
- Central neutral circle has radius = .15, and petals must start from there.
820
-
821
- """
822
-
823
- # Diagonal lines and ticks
824
- step = .03
825
- p1 = (0, 0) # 0, 0 + offset
826
- p2 = _rotate_point((0, 1 + step + offset), angle) # draw line until 0, 1 + step + offset
827
- p3 = _rotate_point((-step, 1 + step + offset), angle) # draw tick
828
- ax.plot([p1[0], p2[0]], [p1[1], p2[1]], zorder = 5, color = 'black', alpha = .3, linewidth = .75)
829
- ax.plot([p2[0], p3[0]], [p2[1], p3[1]], zorder = 5, color = 'black', alpha = .3, linewidth = .75)
830
-
831
- # Managing highlighting and opacity
832
- if highlight == 'opaque':
833
- alpha = .8
834
- color = 'lightgrey'
835
- else:
836
- alpha = 1
837
-
838
-
839
- ## Drawing the two-colored circular arc over dyads
840
- from matplotlib.patches import Arc
841
-
842
- H = 3.2
843
-
844
- pac1 = Arc((0, 0), width = H, height = H, angle = 90, theta2 = angle, theta1 = angle - 18, ec = color[1], linewidth = 3)
845
- pac2 = Arc((0, 0), width = H, height = H, angle = 90, theta2 = angle + 18, theta1 = angle, ec = color[0], linewidth = 3)
846
- ax.add_patch(pac1)
847
- ax.add_patch(pac2)
848
-
849
-
850
- # Labels over the arcs
851
- angle2 = angle + 180 if -110 > angle > -260 else angle
852
- p9 = _rotate_point((0, 1.7), angle - 9)
853
- ax.annotate(s = emotion_names[1], xy = p9, rotation = angle2 - 8, ha='center', va = 'center', zorder = 30,
854
- fontfamily = font, size = fontsize * .7, fontweight = 'demibold', color = color[1])
855
- p10 = _rotate_point((0, 1.7), angle + 9)
856
- ax.annotate(s = emotion_names[0], xy = p10, rotation = angle2 + 8, ha='center', va = 'center', zorder = 30,
857
- fontfamily = font, size = fontsize * .7, fontweight = 'demibold', color = color[0])
858
-
859
-
860
- # Dyad label must be grey
861
- color = '#363636'
862
-
863
- # Label
864
- angle2 = angle + 180 if -110 > angle > -260 else angle
865
- p4 = _rotate_point((0, 1.23 + step + offset), angle)
866
- ax.annotate(s = dyad, xy = p4, rotation = angle2, ha='center', va = 'center',
867
- fontfamily = font, size = fontsize, fontweight = fontweight)
868
-
869
- # Score
870
- p5 = _rotate_point((0, 1.1 + step + offset), angle)
871
- ax.annotate(s = "{0:.2f}".format(round(dyad_score,2)), xy = p5, rotation = angle2, ha='center', va = 'center',
872
- color = color, fontfamily = font, size = fontsize, fontweight = 'demibold', alpha = alpha)
873
-
874
-
875
-
876
-
877
- def _petal_circle(ax, petal, radius, color, inner = False, highlight = 'none', offset = .15, normalize = False):
878
- """
879
- Each petal may have 3 degrees of intensity.
880
- Each of the three sections of a petal is the interception between
881
- the petal and up to two concentric circles from the origin.
882
- This function draws one section.
883
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
884
-
885
- Required arguments:
886
- ----------
887
- *ax*:
888
- Axes to draw the coordinates.
889
-
890
- *petal*:
891
- The petal shape. See petal().
892
-
893
- *radius*:
894
- Radius of the section.
895
-
896
- *color*:
897
- Color of the section. See emo_params().
898
-
899
- *inner*:
900
- Boolean. If True, a second patch is drawn with alpha = 0.3, making the inner circle darker.
901
-
902
- *highlight*:
903
- String. 'opaque' if the petal must be shadowed, 'regular' is default.
904
-
905
- *offset*:
906
- Central neutral circle has radius = .15, and petals must start from there.
907
-
908
- *normalize*:
909
- Either False or the highest value among emotions. If not False, must normalize all petal lengths.
910
-
911
- """
912
-
913
- if radius:
914
-
915
- if normalize:
916
- radius /= normalize
917
-
918
- # Define the intersection between circle c and petal
919
- c = sg.Point(0, 0).buffer(radius + offset)
920
- area = petal.intersection(c)
921
-
922
- # Managing alpha and color
923
- alpha0 = 1 if highlight == 'regular' else .2
924
- ecol = (colors.to_rgba(color)[0], colors.to_rgba(color)[1], colors.to_rgba(color)[2], alpha0)
925
-
926
- alpha1 = .5 if highlight == 'regular' else .0
927
-
928
- # Drawing separately the shape and a thicker border
929
- ax.add_patch(descartes.PolygonPatch(area, fc=color, ec = 'black', lw = 0, alpha=alpha1))
930
- ax.add_patch(descartes.PolygonPatch(area, fc=(0, 0, 0, 0), ec = ecol, lw = 1.3))
931
-
932
- # The innermost circle gets to be brighter because of the repeated overlap
933
- # Its alpha is diminished to avoid too much bright colors
934
- if inner:
935
- alpha2 = .3 if highlight == 'regular' else .0
936
- ax.add_patch(descartes.PolygonPatch(area, fc=color, ec = 'w', lw = 0, alpha=alpha2))
937
- ax.add_patch(descartes.PolygonPatch(area, fc=(0, 0, 0, 0), ec = ecol, lw = 1.5))
938
-
939
-
940
- def _draw_emotion_petal(ax, emotion, emotion_score, highlight_emotions, show_intensity_labels, font, fontweight, fontsize, show_coordinates, height_width_ratio, normalize = False):
941
- """
942
- Draw the petal and its possible sections.
943
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
944
-
945
- Required arguments:
946
- ----------
947
- *ax*:
948
- Axes to draw the coordinates.
949
-
950
- *emotion*:
951
- Emotion's name.
952
-
953
- *emotion_score*:
954
- Score of the emotion. Values range from 0 to 1.
955
-
956
- *highlight_emotions*:
957
- A list of main emotions to highlight. Other emotions will be shadowed.
958
-
959
- *show_intensity_labels*:
960
- A string or a list of main emotions. It shows all three intensity scores for each emotion in the list, and for the others cumulative scores. Default is 'none'.
961
-
962
- *font*:
963
- Font of text. Default is Montserrat.
964
-
965
- *fontweight*:
966
- Font weight of text. Default is light.
967
-
968
- *fontsize*:
969
- Font size of text. Default is 15.
970
-
971
- *offset*:
972
- Central neutral circle has radius = .15, and petals must start from there.
973
-
974
- *show_coordinates*:
975
- A boolean, wether to show polar coordinates or not.
976
-
977
- *normalize*:
978
- Either False or the highest value among emotions. If not False, normalize petal length.
979
-
980
- """
981
- color, angle, _ = emo_params(emotion)
982
-
983
- # Check if iterable
984
- try:
985
- _ = emotion_score[0]
986
- iterable = True
987
- except:
988
- iterable = False
989
-
990
-
991
- # Manage highlight and opacity
992
- if highlight_emotions != 'all':
993
- if emotion in highlight_emotions:
994
- highlight = 'regular'
995
- else:
996
- highlight = 'opaque'
997
- else:
998
- highlight = 'regular'
999
-
1000
-
1001
- if not iterable:
1002
- if show_coordinates:
1003
-
1004
- # Draw the line and tick behind a petal
1005
- _petal_spine_emotion(ax = ax, emotion = emotion, emotion_score = emotion_score,
1006
- color = color, angle = angle,
1007
- font = font, fontweight = fontweight, fontsize = fontsize,
1008
- highlight = highlight,
1009
- offset = .15)
1010
- # Draw petal
1011
- _petal_shape_emotion(ax, emotion_score, color, angle, font, fontweight, fontsize, height_width_ratio = height_width_ratio, highlight = highlight, will_circle = False, normalize = normalize)
1012
- # Draw border
1013
- _outer_border(ax, emotion_score, color, angle, height_width_ratio = height_width_ratio, highlight = highlight, normalize = normalize)
1014
-
1015
- else:
1016
- # Total length is the sum of the emotion score
1017
- a, b, c = emotion_score
1018
- length = a + b + c
1019
- # Show three scores or just the cumulative one?
1020
- label = emotion_score if ((show_intensity_labels == 'all') or (emotion in show_intensity_labels)) else length
1021
-
1022
- if show_coordinates:
1023
-
1024
- # Draw the line and tick behind a petal
1025
- _petal_spine_emotion(ax = ax, emotion = emotion, emotion_score = label,
1026
- color = color, angle = angle,
1027
- font = font, fontweight = fontweight, fontsize = fontsize,
1028
- highlight = highlight,
1029
- offset = .15)
1030
-
1031
- # Draw petal
1032
- petal_shape = _petal_shape_emotion(ax, length, color, angle, font, fontweight, fontsize, height_width_ratio = height_width_ratio, highlight = highlight, will_circle = True, normalize = normalize)
1033
- # Draw inner petal section
1034
- _petal_circle(ax, petal_shape, a + b, color, False, highlight, normalize = normalize)
1035
- # Draw middle petal section
1036
- _petal_circle(ax, petal_shape, a, color, True, highlight, normalize = normalize)
1037
- # Draw border
1038
- _outer_border(ax, length, color, angle, height_width_ratio = height_width_ratio, highlight = highlight, normalize = normalize)
1039
-
1040
-
1041
- def _draw_dyad_petal(ax, dyad, dyad_score, font, fontweight, fontsize, show_coordinates, height_width_ratio, offset = .15, normalize = False):
1042
- """
1043
- Draw the petal and its possible sections.
1044
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
1045
-
1046
- Required arguments:
1047
- ----------
1048
- *ax*:
1049
- Axes to draw the coordinates.
1050
-
1051
- *dyad*:
1052
- Dyad's name.
1053
-
1054
- *dyad_score*:
1055
- Score of the dyad. Values range from 0 to 1.
1056
-
1057
- *font*:
1058
- Font of text. Default is Montserrat.
1059
-
1060
- *fontweight*:
1061
- Font weight of text. Default is light.
1062
-
1063
- *fontsize*:
1064
- Font size of text. Default is 15.
1065
-
1066
- *offset*:
1067
- Central neutral circle has radius = .15, and petals must start from there.
1068
-
1069
- *show_coordinates*:
1070
- A boolean, wether to show polar coordinates or not.
1071
-
1072
- *normalize*:
1073
- Either False or the highest value among the dyads. If not False, normalize petal length.
1074
-
1075
-
1076
- """
1077
- emos, color, angle, _ = dyad_params(dyad)
1078
- colorA, colorB = color
1079
-
1080
- if show_coordinates:
1081
- # Draw the line and tick behind a petal
1082
- _petal_spine_dyad(ax = ax, dyad = dyad, dyad_score = dyad_score,
1083
- emotion_names = emos,
1084
- color = color, angle = angle,
1085
- font = font, fontweight = fontweight, fontsize = fontsize,
1086
- highlight = 'all',
1087
- offset = .15)
1088
-
1089
- # Draw petal (and get the modified ax)
1090
- ax = _petal_shape_dyad(ax, dyad_score, colorA, colorB, angle, font, fontweight, fontsize, height_width_ratio = height_width_ratio, highlight = 'all', will_circle = False, normalize = normalize)
1091
- # Draw border
1092
- _outer_border(ax, dyad_score, colorA, angle, height_width_ratio = height_width_ratio, highlight = 'all', normalize = normalize)
1093
-
1094
-
1095
-
1096
-
1097
-
1098
-
1099
- def _check_scores_kind(tags):
1100
- """
1101
- Checks if the inputed scores are all of the same kind
1102
- (emotions or primary dyads or secondary dyads or tertiary dyads or opposites).
1103
-
1104
- No mixed kinds are allowed.
1105
-
1106
- Required arguments:
1107
- ----------
1108
-
1109
- *tags*:
1110
- List of the tags provided as 'scores'.
1111
-
1112
-
1113
- Returns:
1114
- ----------
1115
-
1116
- A boolean, True if `scores` contains emotions, False if it contains dyads.
1117
-
1118
- """
1119
- kinds = []
1120
- for t in tags:
1121
- try:
1122
- kinds += [emo_params(t)[2]]
1123
- except:
1124
- kinds += [dyad_params(t)[3]]
1125
-
1126
- unique_kinds = list(set(sorted(kinds)))
1127
-
1128
- if len(unique_kinds) > 1:
1129
- unique_kinds_str = ', '.join([str(a) for a in unique_kinds])
1130
- unique_kinds_str = unique_kinds_str.replace('0', 'emotions')
1131
- unique_kinds_str = unique_kinds_str.replace('1', 'primary dyads')
1132
- unique_kinds_str = unique_kinds_str.replace('2', 'secondary dyads')
1133
- unique_kinds_str = unique_kinds_str.replace('3', 'tertiary dyads')
1134
- unique_kinds_str = unique_kinds_str.replace('4', 'opposite emotions')
1135
- unique_kinds_str = ' and'.join(unique_kinds_str.rsplit(',', 1))
1136
-
1137
- error_str = "Bad input: can't draw {} altogether. Please input only one of them as 'scores'.".format(unique_kinds_str)
1138
- raise Exception(error_str)
1139
-
1140
- else:
1141
-
1142
- kind = kinds[0]
1143
-
1144
- if kind == 0:
1145
- return True
1146
- else:
1147
- return False
1148
-
1149
- def random_flower():
1150
- """ Draws a Plutchik's flower with random scores """
1151
-
1152
- import random
1153
-
1154
- emo = {'joy': random.uniform(0, 1),
1155
- 'trust': random.uniform(0,1),
1156
- 'fear': random.uniform(0,1),
1157
- 'surprise': random.uniform(0,1),
1158
- 'sadness': random.uniform(0,1),
1159
- 'disgust': random.uniform(0,1),
1160
- 'anger': random.uniform(0,1),
1161
- 'anticipation': random.uniform(0,1)}
1162
-
1163
- plutchik(emo)
1164
-
1165
- def plutchik(scores,
1166
- ax = None,
1167
- font = None,
1168
- fontweight = 'light',
1169
- fontsize = 15,
1170
- show_coordinates = True,
1171
- show_ticklabels = False,
1172
- highlight_emotions = 'all',
1173
- show_intensity_labels = 'none',
1174
- ticklabels_angle = 0,
1175
- ticklabels_size = 11,
1176
- height_width_ratio = 1,
1177
- title = None,
1178
- title_size = None,
1179
- normalize = False):
1180
- """
1181
- Draw the petal and its possible sections.
1182
- Full details at http://www.github.com/alfonsosemeraro/plutchik/tutorial.ipynb
1183
-
1184
- Required arguments:
1185
- ----------
1186
-
1187
- *scores*:
1188
- A dictionary with emotions or dyads.
1189
- For each entry, values accepted are a 3-values iterable (for emotions only) or a scalar value between 0 and 1.
1190
- The sum of the 3-values iterable values must not exceed 1, and no value should be negative.
1191
- See emo_params() and dyad_params() for accepted keys.
1192
-
1193
- Emotions and dyads are mutually exclusive. Different kinds of dyads are mutually exclusive.
1194
-
1195
- *ax*:
1196
- Axes to draw the coordinates.
1197
-
1198
- *font*:
1199
- Font of text. Default is sans-serif.
1200
-
1201
- *fontweight*:
1202
- Font weight of text. Default is light.
1203
-
1204
- *fontsize*:
1205
- Font size of text. Default is 15.
1206
-
1207
- *offset*:
1208
- Central neutral circle has radius = .15, and petals must start from there.
1209
-
1210
- *show_coordinates*:
1211
- A boolean, wether to show polar coordinates or not.
1212
-
1213
- *show_ticklabels*:
1214
- Boolean, wether to show tick labels under Joy petal. Default is False.
1215
-
1216
- *highlight_emotions*:
1217
- A string or a list of main emotions to highlight. If a list of emotions is given, other emotions will be shadowed. Default is 'all'.
1218
-
1219
- *show_intensity_labels*:
1220
- A string or a list of main emotions. It shows all three intensity scores for each emotion in the list, and for the others cumulative scores. Default is 'none'.
1221
-
1222
- *ticklabels_angle*:
1223
- How much to rotate tick labels from y=0. Value should be given in radians. Default is 0.
1224
-
1225
- *ticklabels_size*:
1226
- Size of tick labels. Default is 11.
1227
-
1228
- *height_width_ratio*:
1229
- Ratio between height and width of the petal. Lower the ratio, thicker the petal. Default is 1.
1230
-
1231
- *title*:
1232
- Title for the plot.
1233
-
1234
- *title_size*:
1235
- Size of the title. Default is font_size.
1236
-
1237
- Returns:
1238
- ----------
1239
- *ax*:
1240
- The input Axes modified.
1241
-
1242
- """
1243
-
1244
- scores = {key.lower(): val for key, val in scores.items()}
1245
-
1246
- # Check if dyads or emotions, and what kind of dyads
1247
- score_is_emotions = _check_scores_kind(scores)
1248
- if score_is_emotions:
1249
- emotions, dyads = scores, None
1250
- else:
1251
- emotions, dyads = None, scores
1252
-
1253
- # Create subplot if is not provided as parameter
1254
- if not ax:
1255
- fig, ax = plt.subplots(figsize = (8, 8))
1256
-
1257
- # Managing fonts
1258
- if not font:
1259
- font = 'sans-serif'
1260
-
1261
-
1262
-
1263
- # Draw coordinates (if needed) before any petal
1264
- if show_coordinates:
1265
- _polar_coordinates(ax, font, fontweight, fontsize, show_ticklabels, ticklabels_angle, ticklabels_size)
1266
-
1267
- # Draw inner white circle
1268
- _neutral_central_circle(ax)
1269
-
1270
-
1271
- # Emotions and dyads are mutually exclusive
1272
- if emotions:
1273
- emotions = {key.lower(): val for key, val in emotions.items()}
1274
-
1275
-
1276
- for emo in emotions:
1277
-
1278
- # Check correctedness of values
1279
- if hasattr(emotions[emo], '__iter__'):
1280
- if sum(emotions[emo]) > 1 or any([e < 0 for e in emotions[emo]]):
1281
- raise Exception("Bad input for `{}`. Emotion scores array should be between 0 and 1.".format(emo))
1282
- else:
1283
- if emotions[emo] > 1 or emotions[emo] < 0:
1284
- raise Exception("Bad input for `{}`. Emotion scores array should sum to between 0 and 1.".format(emo))
1285
-
1286
- # Draw emotion petal
1287
- _draw_emotion_petal(ax, emotion_score = emotions[emo], emotion = emo,
1288
- font = font, fontweight = fontweight, fontsize = fontsize,
1289
- highlight_emotions = highlight_emotions, show_intensity_labels = show_intensity_labels,
1290
- show_coordinates = show_coordinates, height_width_ratio = height_width_ratio, normalize = normalize)
1291
-
1292
- elif dyads:
1293
-
1294
- for dyad in dyads:
1295
-
1296
- # Check correctedness of values
1297
- if dyads[dyad] > 1 or dyads[dyad] < 0:
1298
- print("Alert: {} = {}".format(dyad, dyads[dyad]))
1299
- raise Exception("Bad input for `{}`. Dyads scores array should sum to between 0 and 1.".format(dyad))
1300
-
1301
- # Draw dyad bicolor petal
1302
- _draw_dyad_petal(ax, dyad_score = dyads[dyad], dyad = dyad,
1303
- font = font, fontweight = fontweight, fontsize = fontsize,
1304
- show_coordinates = show_coordinates, height_width_ratio = height_width_ratio,
1305
- normalize = normalize)
1306
-
1307
-
1308
- # Annotation inside the circle
1309
- _, _, _, level = dyad_params(list(dyads.keys())[0]) # get the first dyad level (they all are the same)
1310
- ll = level if level != 4 else 'opp.' # what to annotate
1311
- xy = (-0.03, -0.03) if level != 4 else (-0.13, -0.03) # exact center of '1' or 'opp' is slightly different
1312
- ax.annotate(s = ll, xy = xy, fontsize = fontsize, fontfamily = font, fontweight = 'bold', zorder = 30)
1313
-
1314
- # Ghost dotted track that connects colored arcs
1315
- c = plt.Circle((0, 0), 1.60, color = 'grey', alpha = .3, fill = False, zorder = -20, linestyle = 'dotted' )
1316
- ax.add_artist(c)
1317
-
1318
-
1319
- # Adjusting printable area size
1320
- lim = 1.6 if show_coordinates else 1.2
1321
- lim = lim + 0.1 if dyads else lim
1322
-
1323
- ax.set_xlim((-lim, lim))
1324
- ax.set_ylim((-lim, lim))
1325
-
1326
- # Default is no axis
1327
- ax.axis('off')
1328
-
1329
- # Title and title size
1330
- if not title_size:
1331
- title_size = fontsize
1332
-
1333
- if title:
1334
- ax.set_title(title, fontfamily = font, fontsize = title_size, fontweight = 'bold', pad = 20)
1335
-
1336
- return ax