@@ -78,7 +78,7 @@ class layer:
7878
7979 def __init__ (
8080 self ,
81- geom : geom | type [geom ] | str = "blank" ,
81+ geom : geom | type [geom ] | str | None = None ,
8282 stat : stat | type [stat ] | str | None = None ,
8383 * ,
8484 mapping : aes | None = None ,
@@ -89,15 +89,31 @@ def __init__(
8989 raster : bool = False ,
9090 ** kwargs : Any ,
9191 ):
92+ # Stat-first: derive geom from stat's default
93+ if stat is not None :
94+ stat_ref = _lookup_stat (stat )
95+ if isinstance (stat_ref , type ):
96+ geom = stat_ref .DEFAULT_PARAMS .get ("geom" , "blank" )
97+ else :
98+ geom = stat_ref .params .get ("geom" , "blank" )
99+ # Forward stat instance's kwargs to the geom
100+ if mapping is None and data is None and not kwargs :
101+ mapping = stat_ref ._raw_kwargs .get ("mapping" )
102+ data = stat_ref ._raw_kwargs .get ("data" )
103+ kwargs = {
104+ k : v
105+ for k , v in stat_ref ._raw_kwargs .items ()
106+ if k not in ("mapping" , "data" )
107+ }
108+
109+ if geom is None :
110+ geom = "blank"
111+
92112 _geom = _resolve_geom (geom , mapping , data , kwargs )
93113 _stat = _resolve_stat (stat , _geom )
94114 _pos = _resolve_position (position , _geom )
95115 self ._verify_arguments (_geom , _stat )
96116
97- # Set back-references for pipeline compat
98- _geom ._stat = _stat # pyright: ignore[reportAttributeAccessIssue]
99- _geom ._position = _pos # pyright: ignore[reportAttributeAccessIssue]
100-
101117 # Layer params: prefer explicit kwargs, fall back to
102118 # geom._raw_kwargs, then geom.DEFAULT_PARAMS
103119 raw = _geom ._raw_kwargs
@@ -121,56 +137,6 @@ def __init__(
121137 self .position = _pos
122138 self .zorder = 0
123139
124- @staticmethod
125- def from_geom (geom : geom ) -> layer :
126- """
127- Create a layer given a [](`~plotnine.geoms.geom`)
128-
129- Parameters
130- ----------
131- geom :
132- `geom` from which a layer will be created
133-
134- Returns
135- -------
136- :
137- Layer that represents the specific `geom`.
138- """
139- return layer (geom = geom )
140-
141- @staticmethod
142- def from_stat (stat : stat ) -> layer :
143- """
144- Create a layer given a [](`~plotnine.stats.stat`)
145-
146- Parameters
147- ----------
148- stat :
149- `stat` from which a layer will be created
150-
151- Returns
152- -------
153- :
154- Layer that represents the specific `stat`.
155- """
156- from .geoms .geom import geom as geom_cls
157-
158- name = stat .params .get ("geom" , "blank" )
159-
160- if isinstance (name , geom_cls ):
161- return layer (geom = name )
162-
163- if isinstance (name , type ) and issubclass (name , geom_cls ):
164- klass = name
165- elif isinstance (name , str ):
166- if not name .startswith ("geom_" ):
167- name = f"geom_{ name } "
168- klass = Registry [name ]
169- else :
170- raise PlotnineError (f"Unknown geom of type { type (name )} " )
171-
172- return layer (geom = klass (stat = stat , ** stat ._raw_kwargs ))
173-
174140 @staticmethod
175141 def _verify_arguments (geom : geom , stat : stat ) -> None :
176142 """
@@ -683,6 +649,43 @@ def _resolve_geom(
683649 return klass (mapping , data , ** kwargs )
684650
685651
652+ def _lookup_stat (
653+ stat_spec : stat | type [stat ] | str ,
654+ ) -> stat | type [stat ]:
655+ """
656+ Look up a stat specification without instantiation
657+
658+ Parameters
659+ ----------
660+ stat_spec :
661+ A stat instance, class, or string name.
662+
663+ Returns
664+ -------
665+ :
666+ The stat instance or class.
667+ """
668+ from .stats .stat import stat as stat_cls
669+
670+ # Duck-type guard for module reloads
671+ if not isinstance (stat_spec , type ) and hasattr (stat_spec , "compute_layer" ):
672+ return stat_spec # type: ignore[return-value]
673+
674+ if isinstance (stat_spec , stat_cls ):
675+ return stat_spec
676+
677+ if isinstance (stat_spec , type ) and issubclass (stat_spec , stat_cls ):
678+ return stat_spec
679+
680+ if isinstance (stat_spec , str ):
681+ name = stat_spec
682+ if not name .startswith ("stat_" ):
683+ name = f"stat_{ name } "
684+ return Registry [name ]
685+
686+ raise PlotnineError (f"Unknown stat of type { type (stat_spec )} " )
687+
688+
686689def _resolve_stat (
687690 stat_spec : stat | type [stat ] | str | None ,
688691 geom_obj : geom ,
@@ -703,24 +706,13 @@ def _resolve_stat(
703706 if stat_spec is None :
704707 stat_spec = geom_obj .params ["stat" ]
705708
706- # Duck-type guard for module reloads
707- if not isinstance (stat_spec , type ) and hasattr (stat_spec , "compute_layer" ):
708- return stat_spec # type: ignore[return-value]
709-
710- if isinstance (stat_spec , stat_cls ):
711- return stat_spec
709+ result = _lookup_stat (stat_spec ) # type: ignore[arg-type]
712710
713- if isinstance (stat_spec , type ) and issubclass (stat_spec , stat_cls ):
714- klass = stat_spec
715- elif isinstance (stat_spec , str ):
716- name = stat_spec
717- if not name .startswith ("stat_" ):
718- name = f"stat_{ name } "
719- klass = Registry [name ]
720- else :
721- raise PlotnineError (f"Unknown stat of type { type (stat_spec )} " )
711+ if isinstance (result , stat_cls ):
712+ return result
722713
723- # Filter geom's raw kwargs to stat-relevant keys
714+ # It's a class — instantiate with filtered geom kwargs
715+ klass = result
724716 kwargs = geom_obj ._raw_kwargs
725717 valid_kwargs = (
726718 klass .aesthetics () | klass .DEFAULT_PARAMS .keys ()
0 commit comments