A more coherent version by ChatGPT
“”"
After completing the development of what I consider one of my most refined applications yet (Year vs Climatology - a Hugging Face Space by ahuang11), I realized it encompasses numerous examples of best practices, mostly drawn from my experience using HoloViz. In a spontaneous decision, I decided to compile a somewhat unpolished brain dump of these practices:
- Instead of inheriting from
param.Parameterized, opting for inheritance frompn.viewable.Viewerallows direct invocation of the class, resembling a native Panel object. This eliminates the need for calling a method likeClimateApp().view().servable(). - To ensure sliders only trigger callbacks upon mouse-up, set
throttled=True. - Start by instantiating the initial layout with placeholder
pn.Columnsin__init__, then populate it later inonload. - Enhance app responsiveness by employing
onloadto prevent webpage hang-ups during slow loading processes. Users can immediately observe a loading indicator upon visiting, signaling ongoing processing. - Manage loading states effectively by encapsulating widget activation within a
try/finallyblock. This ensures widgets are always reactivated upon completion or in the event of errors. - Utilize
pn.Paramorfrom_paramclassmethod for converting class parameters to widgets, with the latter particularly useful for handling nested dictionaries. - Renaming widget names can be achieved using
labelwhen utilizingpn.Paramorfrom_param. - Ensure proper param watching/binding by using
self.param.NAME_OF_PARAMinstead ofself.NAME_OF_PARAM, noting the additional.param.. - Optimize runtime and reduce flickers by updating
objectandvalueon pre-initialized placeholders instead of recreating the panel object every timepn.bindruns. - Preserve plot zoom ranges during updates by wrapping
hv.DynamicMapwithpn.bind. This prevents the plot from resetting zoom, although some bugs may necessitate workarounds for issues like title/ylabel updating. - Enhance app speed using
@pn.cache, but remember thatpn.cacheactivation depends on input kwargs. - Employ
pn.dependswithwatch=Truewhen a method doesn’t return anything. - Utilize a template’s
modal(pop-up container) to optimize screen estate if unsure where else to place content. - Bind to HoloViews streams, noting similarities and differences between
hv.DynamicMap streamsandpn.bind. - Prevent text overlapping by setting opposites with text align and baseline.
My approach typically involves:
- Starting with small iterations, gradually building up functionality. The
panel serve app.py --autoreloadcommand proves handy in this regard. - Focusing initially on layout, ensuring the core structure looks correct.
- Introducing interactivity with
pn.bindorpn.dependsonce the layout is satisfactory.
I continuously iterate through these steps when implementing new features, beginning with creating placeholder widgets/panes, verifying visual correctness, and finally adding interactivity. If any of these concepts require clarification, feel free to ask!
“”"