@@ -25,6 +25,7 @@ def build_figure_py(
25
25
layout_validator ,
26
26
frame_validator ,
27
27
subplot_nodes ,
28
+ layout_array_nodes ,
28
29
):
29
30
"""
30
31
@@ -47,6 +48,8 @@ def build_figure_py(
47
48
FrameValidator instance
48
49
subplot_nodes: list of str
49
50
List of names of all of the layout subplot properties
51
+ layout_array_nodes: list of PlotlyNode
52
+ List of array nodes under layout that can be positioned using xref/yref
50
53
Returns
51
54
-------
52
55
str
@@ -66,8 +69,10 @@ def build_figure_py(
66
69
# ### Import base class ###
67
70
buffer .write (f"from plotly.{ base_package } import { base_classname } \n " )
68
71
69
- # ### Import trace graph_obj classes ###
70
- trace_types_csv = ", " .join ([n .name_datatype_class for n in trace_nodes ])
72
+ # ### Import trace graph_obj classes / layout ###
73
+ trace_types_csv = ", " .join (
74
+ [n .name_datatype_class for n in trace_nodes ] + ["layout as _layout" ]
75
+ )
71
76
buffer .write (f"from plotly.graph_objs import ({ trace_types_csv } )\n " )
72
77
73
78
# Write class definition
@@ -358,14 +363,253 @@ def update_{plural_name}(
358
363
return self"""
359
364
)
360
365
366
+ # update annotations/shapes/images
367
+ # --------------------------------
368
+ for node in layout_array_nodes :
369
+ singular_name = node .plotly_name
370
+ plural_name = node .name_property
371
+
372
+ if singular_name == "image" :
373
+ # Rename image to layout_image to avoid conflict with an image trace
374
+ method_prefix = "layout_"
375
+ else :
376
+ method_prefix = ""
377
+
378
+ buffer .write (
379
+ f"""
380
+ def select_{ method_prefix } { plural_name } (
381
+ self, selector=None, row=None, col=None, secondary_y=None
382
+ ):
383
+ \" \" \"
384
+ Select { plural_name } from a particular subplot cell and/or { plural_name }
385
+ that satisfy custom selection criteria.
386
+
387
+ Parameters
388
+ ----------
389
+ selector: dict or None (default None)
390
+ Dict to use as selection criteria.
391
+ Annotations will be selected if they contain properties corresponding
392
+ to all of the dictionary's keys, with values that exactly match
393
+ the supplied values. If None (the default), all { plural_name } are
394
+ selected.
395
+ row, col: int or None (default None)
396
+ Subplot row and column index of { plural_name } to select.
397
+ To select { plural_name } by row and column, the Figure must have been
398
+ created using plotly.subplots.make_subplots. To select only those
399
+ { singular_name } that are in paper coordinates, set row and col to the
400
+ string 'paper'. If None (the default), all { plural_name } are selected.
401
+ secondary_y: boolean or None (default None)
402
+ * If True, only select { plural_name } associated with the secondary
403
+ y-axis of the subplot.
404
+ * If False, only select { plural_name } associated with the primary
405
+ y-axis of the subplot.
406
+ * If None (the default), do not filter { plural_name } based on secondary
407
+ y-axis.
408
+
409
+ To select { plural_name } by secondary y-axis, the Figure must have been
410
+ created using plotly.subplots.make_subplots. See the docstring
411
+ for the specs argument to make_subplots for more info on
412
+ creating subplots with secondary y-axes.
413
+ Returns
414
+ -------
415
+ generator
416
+ Generator that iterates through all of the { plural_name } that satisfy
417
+ all of the specified selection criteria
418
+ \" \" \"
419
+ return self._select_annotations_like(
420
+ "{ plural_name } ", selector=selector, row=row, col=col, secondary_y=secondary_y
421
+ )
422
+
423
+ def for_each_{ method_prefix } { singular_name } (
424
+ self, fn, selector=None, row=None, col=None, secondary_y=None
425
+ ):
426
+ \" \" \"
427
+ Apply a function to all { plural_name } that satisfy the specified selection
428
+ criteria
429
+
430
+ Parameters
431
+ ----------
432
+ fn:
433
+ Function that inputs a single { singular_name } object.
434
+ selector: dict or None (default None)
435
+ Dict to use as selection criteria.
436
+ Traces will be selected if they contain properties corresponding
437
+ to all of the dictionary's keys, with values that exactly match
438
+ the supplied values. If None (the default), all { plural_name } are
439
+ selected.
440
+ row, col: int or None (default None)
441
+ Subplot row and column index of { plural_name } to select.
442
+ To select { plural_name } by row and column, the Figure must have been
443
+ created using plotly.subplots.make_subplots. To select only those
444
+ { plural_name } that are in paper coordinates, set row and col to the
445
+ string 'paper'. If None (the default), all { plural_name } are selected.
446
+ secondary_y: boolean or None (default None)
447
+ * If True, only select { plural_name } associated with the secondary
448
+ y-axis of the subplot.
449
+ * If False, only select { plural_name } associated with the primary
450
+ y-axis of the subplot.
451
+ * If None (the default), do not filter { plural_name } based on secondary
452
+ y-axis.
453
+
454
+ To select { plural_name } by secondary y-axis, the Figure must have been
455
+ created using plotly.subplots.make_subplots. See the docstring
456
+ for the specs argument to make_subplots for more info on
457
+ creating subplots with secondary y-axes.
458
+ Returns
459
+ -------
460
+ self
461
+ Returns the Figure object that the method was called on
462
+ \" \" \"
463
+ for obj in self._select_annotations_like(
464
+ prop='{ plural_name } ',
465
+ selector=selector,
466
+ row=row,
467
+ col=col,
468
+ secondary_y=secondary_y,
469
+ ):
470
+ fn(obj)
471
+
472
+ return self
473
+
474
+ def update_{ method_prefix } { plural_name } (
475
+ self,
476
+ patch,
477
+ selector=None,
478
+ row=None,
479
+ col=None,
480
+ secondary_y=None,
481
+ **kwargs
482
+ ):
483
+ \" \" \"
484
+ Perform a property update operation on all { plural_name } that satisfy the
485
+ specified selection criteria
486
+
487
+ Parameters
488
+ ----------
489
+ patch: dict or None (default None)
490
+ Dictionary of property updates to be applied to all { plural_name } that
491
+ satisfy the selection criteria.
492
+ selector: dict or None (default None)
493
+ Dict to use as selection criteria.
494
+ Traces will be selected if they contain properties corresponding
495
+ to all of the dictionary's keys, with values that exactly match
496
+ the supplied values. If None (the default), all { plural_name } are
497
+ selected.
498
+ row, col: int or None (default None)
499
+ Subplot row and column index of { plural_name } to select.
500
+ To select { plural_name } by row and column, the Figure must have been
501
+ created using plotly.subplots.make_subplots. To select only those
502
+ { singular_name } that are in paper coordinates, set row and col to the
503
+ string 'paper'. If None (the default), all { plural_name } are selected.
504
+ secondary_y: boolean or None (default None)
505
+ * If True, only select { plural_name } associated with the secondary
506
+ y-axis of the subplot.
507
+ * If False, only select { plural_name } associated with the primary
508
+ y-axis of the subplot.
509
+ * If None (the default), do not filter { plural_name } based on secondary
510
+ y-axis.
511
+
512
+ To select { plural_name } by secondary y-axis, the Figure must have been
513
+ created using plotly.subplots.make_subplots. See the docstring
514
+ for the specs argument to make_subplots for more info on
515
+ creating subplots with secondary y-axes.
516
+ **kwargs
517
+ Additional property updates to apply to each selected { singular_name } . If
518
+ a property is specified in both patch and in **kwargs then the
519
+ one in **kwargs takes precedence.
520
+
521
+ Returns
522
+ -------
523
+ self
524
+ Returns the Figure object that the method was called on
525
+ \" \" \"
526
+ for obj in self._select_annotations_like(
527
+ prop='{ plural_name } ',
528
+ selector=selector,
529
+ row=row,
530
+ col=col,
531
+ secondary_y=secondary_y,
532
+ ):
533
+ obj.update(patch, **kwargs)
534
+
535
+ return self
536
+ """
537
+ )
538
+ # Add layout array items
539
+ buffer .write (
540
+ f"""
541
+ def add_{ method_prefix } { singular_name } (self"""
542
+ )
543
+ add_constructor_params (
544
+ buffer ,
545
+ node .child_datatypes ,
546
+ prepend_extras = ["arg" ],
547
+ append_extras = ["row" , "col" , "secondary_y" ],
548
+ )
549
+
550
+ prepend_extras = [
551
+ (
552
+ "arg" ,
553
+ f"instance of { node .name_datatype_class } or dict with "
554
+ "compatible properties" ,
555
+ )
556
+ ]
557
+ append_extras = [
558
+ ("row" , f"Subplot row for { singular_name } " ),
559
+ ("col" , f"Subplot column for { singular_name } " ),
560
+ ("secondary_y" , f"Whether to add { singular_name } to secondary y-axis" ),
561
+ ]
562
+ add_docstring (
563
+ buffer ,
564
+ node ,
565
+ header = f"Create and add a new { singular_name } to the figure's layout" ,
566
+ prepend_extras = prepend_extras ,
567
+ append_extras = append_extras ,
568
+ return_type = fig_classname ,
569
+ )
570
+
571
+ # #### Function body ####
572
+ buffer .write (
573
+ f"""
574
+ new_obj = _layout.{ node .name_datatype_class } (arg,
575
+ """
576
+ )
577
+
578
+ for i , subtype_node in enumerate (node .child_datatypes ):
579
+ subtype_prop_name = subtype_node .name_property
580
+ buffer .write (
581
+ f"""
582
+ { subtype_prop_name } ={ subtype_prop_name } ,"""
583
+ )
584
+
585
+ buffer .write ("""**kwargs)""" )
586
+
587
+ buffer .write (
588
+ f"""
589
+ return self._add_annotation_like(
590
+ '{ singular_name } ',
591
+ '{ plural_name } ',
592
+ new_obj,
593
+ row=row,
594
+ col=col,
595
+ secondary_y=secondary_y,
596
+ )"""
597
+ )
598
+
361
599
# Return source string
362
600
# --------------------
363
601
buffer .write ("\n " )
364
602
return buffer .getvalue ()
365
603
366
604
367
605
def write_figure_classes (
368
- outdir , trace_node , data_validator , layout_validator , frame_validator , subplot_nodes
606
+ outdir ,
607
+ trace_node ,
608
+ data_validator ,
609
+ layout_validator ,
610
+ frame_validator ,
611
+ subplot_nodes ,
612
+ layout_array_nodes ,
369
613
):
370
614
"""
371
615
Construct source code for the Figure and FigureWidget classes and
@@ -385,9 +629,10 @@ def write_figure_classes(
385
629
LayoutValidator instance
386
630
frame_validator : CompoundArrayValidator
387
631
FrameValidator instance
388
- subplot_nodes: list of str
632
+ subplot_nodes: list of PlotlyNode
389
633
List of names of all of the layout subplot properties
390
-
634
+ layout_array_nodes: list of PlotlyNode
635
+ List of array nodes under layout that can be positioned using xref/yref
391
636
Returns
392
637
-------
393
638
None
@@ -420,6 +665,7 @@ def write_figure_classes(
420
665
layout_validator ,
421
666
frame_validator ,
422
667
subplot_nodes ,
668
+ layout_array_nodes ,
423
669
)
424
670
425
671
# ### Format and write to file###
0 commit comments