Zulip Templates & Examples ๐
Ready-to-use notification patterns for research workflows
This guide provides practical templates and examples for common research scenarios using Zulip integration. Copy these patterns and adapt them to your specific needs.
๐๏ธ Channel & Topic Organization
Recommended Channel Structure
๐ Your Research Organization
โโโ ๐ฌ personal-alerts # Your private notifications
โโโ ๐ฅ team-research # Shared research updates
โโโ ๐ฅ๏ธ simulations # Simulation runs and results
โโโ ๐ data-analysis # Analysis pipelines and plots
โโโ ๐ publications # Paper-related results
โโโ ๐จ errors # Error notifications and debugging
โโโ ๐พ backups # Backup and maintenance alerts
โโโ ๐ฏ milestones # Project milestones and achievements
Topic Naming Conventions
Good topic names:
"Temperature Analysis - Aug 2024"
"Galaxy Survey Processing - NGC4321"
"Parameter Sweep #47 - Mass Function"
"Paper 1 - Final Figures"
Avoid:
"Results"
(too vague)"Test"
(not searchable later)"Untitled"
(no context)
๐ Research Workflow Templates
1. Daily Analysis Pipeline
"""Template for daily/routine analysis workflows"""
function daily_temperature_analysis(survey_name::String, date::String)
# Initialize with clear identification
notifyme("๐
Starting daily temperature analysis",
zulip_channel="data-analysis",
zulip_topic="Temperature Pipeline - $date")
start_time = time()
try
# Step 1: Data loading
data = load_survey_data(survey_name)
notifyme("โ
Loaded $(length(data.galaxies)) galaxies from $survey_name",
zulip_channel="data-analysis",
zulip_topic="Temperature Pipeline - $date")
# Step 2: Analysis with progress tracking
results = analyze_temperatures(data)
# Step 3: Generate plots
plot_path = create_temperature_plots(results)
# Step 4: Final notification with results
notifyme("๐ **Daily temperature analysis complete!**\\n\\n" *
"โข Galaxies analyzed: $(length(data.galaxies))\\n" *
"โข Mean temperature: $(round(results.mean_temp, digits=2)) K\\n" *
"โข Analysis time: $(round((time()-start_time)/60, digits=1)) minutes",
image_path=plot_path,
start_time=start_time,
zulip_channel="data-analysis",
zulip_topic="Temperature Pipeline - $date")
return results
catch e
notifyme("โ Daily temperature analysis FAILED for $date",
exception_context=e,
start_time=start_time,
zulip_channel="errors",
zulip_topic="Pipeline Failures - $date")
rethrow(e)
end
end
2. Long-Running Simulation Monitor
"""Template for monitoring overnight/weekend simulations"""
function run_galaxy_formation_simulation(config_name::String)
# Create dedicated topic for this simulation
topic = "Galaxy Formation - $config_name - $(Dates.format(now(), "yyyy-mm-dd"))"
# Initial startup notification
notifyme("๐ **Starting Galaxy Formation Simulation**\\n\\n" *
"โข Configuration: $config_name\\n" *
"โข Expected duration: ~8-12 hours\\n" *
"โข Progress updates every 30 minutes",
zulip_channel="simulations",
zulip_topic=topic)
# Progress tracking setup
total_timesteps = 1000
tracker = create_progress_tracker(total_timesteps,
task_name="Galaxy Formation ($config_name)",
time_interval=1800, # 30-minute updates
progress_interval=5, # Every 5%
zulip_channel="simulations",
zulip_topic=topic)
start_time = time()
try
simulation_data = initialize_simulation(config_name)
# Main simulation loop with monitoring
for timestep in 1:total_timesteps
evolve_timestep!(simulation_data, timestep)
update_progress!(tracker, timestep)
# Special checkpoints
if timestep in [100, 250, 500, 750]
checkpoint_path = save_checkpoint(simulation_data, timestep)
notifyme("๐ธ **Checkpoint saved at timestep $timestep**\\n\\n" *
"โข Galaxies formed: $(count_galaxies(simulation_data))\\n" *
"โข Current redshift: $(current_redshift(simulation_data))",
image_path=checkpoint_path,
zulip_channel="simulations",
zulip_topic=topic)
end
end
# Final results
final_plots = create_final_plots(simulation_data)
complete_progress!(tracker,
"๐ **Simulation completed successfully!**\\n\\n" *
"โข Final galaxy count: $(count_galaxies(simulation_data))\\n" *
"โข Total mass assembled: $(total_mass(simulation_data)) Mโ\\n" *
"โข Data saved to: $(save_simulation_results(simulation_data))")
# Share all final plots
send_results("๐ **Final simulation results - $config_name**",
final_plots,
zulip_channel="simulations",
zulip_topic=topic)
return simulation_data
catch e
notifyme("๐ฅ **SIMULATION CRASHED** - $config_name\\n\\n" *
"โข Failed at timestep: $(get_current_timestep())\\n" *
"โข Checkpoint data may be recoverable\\n" *
"โข Check error logs for debugging",
exception_context=e,
start_time=start_time,
zulip_channel="errors",
zulip_topic="Simulation Failures")
rethrow(e)
end
end
3. Parameter Study Management
"""Template for parameter sweeps and systematic studies"""
function run_parameter_sweep(parameter_name::String, parameter_values::Vector)
sweep_id = "$(parameter_name)_sweep_$(Dates.format(now(), "yyyymmdd_HHMM"))"
topic = "Parameter Sweep - $parameter_name"
# Initialize sweep
notifyme("๐ฌ **Starting Parameter Sweep**\\n\\n" *
"โข Parameter: $parameter_name\\n" *
"โข Values: $(length(parameter_values)) points\\n" *
"โข Range: $(minimum(parameter_values)) - $(maximum(parameter_values))\\n" *
"โข Sweep ID: $sweep_id",
zulip_channel="data-analysis",
zulip_topic=topic)
results = Dict()
failed_params = []
# Track overall progress
tracker = create_progress_tracker(length(parameter_values),
task_name="Parameter Sweep ($parameter_name)",
time_interval=600, # 10-minute updates
progress_interval=10, # Every 10%
zulip_channel="data-analysis",
zulip_topic=topic)
for (i, param_value) in enumerate(parameter_values)
try
# Run single parameter point
result = safe_execute("$parameter_name = $param_value") do
run_analysis_with_parameter(parameter_name, param_value)
end
results[param_value] = result
update_progress!(tracker, i)
catch e
push!(failed_params, param_value)
notifyme("โ ๏ธ **Parameter point failed: $parameter_name = $param_value**",
exception_context=e,
zulip_channel="errors",
zulip_topic="Parameter Sweep Failures")
continue
end
end
# Generate summary plots
summary_plots = create_parameter_sweep_plots(results, parameter_name)
# Final summary
success_count = length(results)
failure_count = length(failed_params)
complete_progress!(tracker,
"๐ **Parameter sweep completed!**\\n\\n" *
"โข Successful runs: $success_count/$(length(parameter_values))\\n" *
"โข Failed parameters: $failed_params\\n" *
"โข Results saved to: $(save_parameter_results(results, sweep_id))")
# Share summary plots
send_results("๐ **Parameter sweep summary - $parameter_name**",
summary_plots,
zulip_channel="data-analysis",
zulip_topic=topic)
return results, failed_params
end
๐ Publication & Paper Workflows
4. Paper Figure Generation
"""Template for generating publication-quality figures"""
function generate_paper_figures(paper_name::String, figure_specs::Dict)
topic = "Paper: $paper_name - Figures"
notifyme("๐ **Starting figure generation for $paper_name**\\n\\n" *
"โข Figures to generate: $(length(figure_specs))\\n" *
"โข Target journal: $(get(figure_specs, :journal, \"TBD\"))\\n" *
"โข Figure specifications loaded",
zulip_channel="publications",
zulip_topic=topic)
figure_paths = String[]
for (fig_name, spec) in figure_specs
try
notifyme("๐จ Generating Figure: $fig_name",
zulip_channel="publications",
zulip_topic=topic)
fig_path = timed_notify("Figure $fig_name generation") do
create_publication_figure(fig_name, spec)
end
push!(figure_paths, fig_path)
# Send individual figure for quick review
notifyme("โ
**Figure ready: $fig_name**\\n\\n" *
"โข Resolution: $(spec.resolution) DPI\\n" *
"โข Format: $(spec.format)\\n" *
"โข Size: $(get_file_size(fig_path)) MB",
image_path=fig_path,
zulip_channel="publications",
zulip_topic=topic)
catch e
notifyme("โ **Failed to generate figure: $fig_name**",
exception_context=e,
zulip_channel="errors",
zulip_topic="Publication Failures")
end
end
# Final collection
send_results("๐ **All figures complete - $paper_name**\\n\\n" *
"Ready for manuscript integration!",
figure_paths,
max_files=20, # Allow more files for papers
zulip_channel="publications",
zulip_topic=topic)
return figure_paths
end
5. Team Collaboration Template
"""Template for team-shared analysis with role-specific notifications"""
function shared_galaxy_analysis(dataset_name::String, team_members::Dict)
analysis_id = "$(dataset_name)_$(Dates.format(now(), "yyyymmdd"))"
topic = "Team Analysis - $dataset_name"
# Notify start to team channel
notifyme("๐ฅ **Team Analysis Started: $dataset_name**\\n\\n" *
"โข Analysis ID: $analysis_id\\n" *
"โข Team members: $(join(keys(team_members), \", \"))\\n" *
"โข Estimated completion: 2-3 hours\\n" *
"โข Progress updates will be posted here",
zulip_channel="team-research",
zulip_topic=topic)
# Notify individual team members in their channels
for (member, role) in team_members
member_channel = "personal-$(lowercase(member))"
notifyme("๐ฏ **Your role in $dataset_name analysis:**\\n\\n" *
"โข Role: $role\\n" *
"โข Analysis ID: $analysis_id\\n" *
"โข Updates in #team-research > $topic",
zulip_channel=member_channel,
zulip_topic="Team Assignments")
end
start_time = time()
try
# Step 1: Data preparation
data = prepare_team_dataset(dataset_name)
notifyme("๐ **Data prepared for team analysis**\\n\\n" *
"โข Galaxies: $(length(data.galaxies))\\n" *
"โข Redshift range: $(data.z_min) - $(data.z_max)\\n" *
"โข Data validation: โ
Complete",
zulip_channel="team-research",
zulip_topic=topic)
# Step 2: Parallel analysis sections
results = run_parallel_analysis(data, team_members)
# Step 3: Integration and final plots
integrated_results = integrate_team_results(results)
final_plots = create_team_summary_plots(integrated_results)
# Final team notification
notifyme("๐ **Team analysis complete - $dataset_name!**\\n\\n" *
"โข Total execution time: $(round((time()-start_time)/3600, digits=1)) hours\\n" *
"โข All team sections completed successfully\\n" *
"โข Results ready for review and discussion",
start_time=start_time,
zulip_channel="team-research",
zulip_topic=topic)
# Send plots to team
send_results("๐ **Team analysis results - $dataset_name**",
final_plots,
zulip_channel="team-research",
zulip_topic=topic)
# Individual completion notifications
for member in keys(team_members)
member_channel = "personal-$(lowercase(member))"
notifyme("โ
**Team analysis completed!**\\n\\n" *
"Results available in #team-research > $topic\\n" *
"Your contributions have been integrated successfully.",
zulip_channel=member_channel,
zulip_topic="Team Assignments")
end
return integrated_results
catch e
# Team-wide error notification
notifyme("๐ฅ **Team analysis failed - $dataset_name**\\n\\n" *
"Please check individual error channels for details\\n" *
"Analysis ID: $analysis_id",
exception_context=e,
start_time=start_time,
zulip_channel="errors",
zulip_topic="Team Analysis Failures")
rethrow(e)
end
end
๐ ๏ธ System Maintenance Templates
6. Backup & Maintenance Notifications
"""Template for system maintenance and backup operations"""
function weekly_maintenance_routine()
topic = "System Maintenance - $(Dates.format(now(), \"yyyy-mm-dd\"))"
notifyme("๐ง **Weekly maintenance routine starting**\\n\\n" *
"โข Backup verification\\n" *
"โข Disk space cleanup\\n" *
"โข System health check\\n" *
"โข Estimated time: 30-45 minutes",
zulip_channel="backups",
zulip_topic=topic)
maintenance_start = time()
results = Dict()
# System info before maintenance
notifyme("๐ **Pre-maintenance system status:**",
capture_output=get_system_info_command(),
zulip_channel="backups",
zulip_topic=topic)
try
# Backup verification
backup_status = verify_backups()
results[:backup] = backup_status
notifyme("๐พ **Backup verification:** $(backup_status.status)\\n\\n" *
"โข Last backup: $(backup_status.last_backup)\\n" *
"โข Size: $(backup_status.total_size) GB\\n" *
"โข Integrity: $(backup_status.integrity_check)",
zulip_channel="backups",
zulip_topic=topic)
# Disk cleanup
cleanup_results = clean_temp_files()
results[:cleanup] = cleanup_results
notifyme("๐งน **Disk cleanup completed**\\n\\n" *
"โข Space freed: $(cleanup_results.space_freed) GB\\n" *
"โข Files removed: $(cleanup_results.files_count)\\n" *
"โข Directories cleaned: $(length(cleanup_results.directories))",
zulip_channel="backups",
zulip_topic=topic)
# Final system status
notifyme("โ
**Weekly maintenance completed!**\\n\\n" *
"โข Total time: $(round((time()-maintenance_start)/60, digits=1)) minutes\\n" *
"โข All checks passed\\n" *
"โข System ready for next week",
start_time=maintenance_start,
capture_output=get_disk_info_command(),
zulip_channel="backups",
zulip_topic=topic)
return results
catch e
notifyme("๐จ **Maintenance routine failed!**\\n\\n" *
"Manual intervention required\\n" *
"Check system logs for details",
exception_context=e,
start_time=maintenance_start,
zulip_channel="errors",
zulip_topic="System Maintenance Failures")
rethrow(e)
end
end
๐จ Custom Message Templates
Rich Formatting Examples
# Progress update with emojis and formatting
function format_progress_update(current, total, task_name, details)
progress_percent = round((current/total) * 100, digits=1)
progress_bar = create_text_progress_bar(current, total, width=10)
return """
๐ **$task_name Progress Update**
$progress_bar $progress_percent% ($current/$total)
**Details:**
$(join(["โข $detail" for detail in details], "\n"))
**ETA:** $(estimate_remaining_time(current, total)) minutes
"""
end
# Error report with context
function format_error_notification(error, context, suggestions)
return """
โ **Error Detected**
**Error Type:** $(typeof(error))
**Message:** $(string(error))
**Context:**
$(join(["โข $ctx" for ctx in context], "\n"))
**Suggested Actions:**
$(join(["๐ง $suggestion" for suggestion in suggestions], "\n"))
**Timestamp:** $(now())
"""
end
# Results summary with statistics
function format_results_summary(results, metrics, plots)
return """
๐ **Analysis Complete!**
**Key Results:**
$(join(["โข $key: $value" for (key, value) in results], "\n"))
**Performance Metrics:**
$(join(["๐ $metric: $value" for (metric, value) in metrics], "\n"))
**Generated Plots:** $(length(plots))
๐ Ready for review and publication
"""
end
๐ง Configuration Helpers
Environment-Specific Settings
# Development vs Production notifications
function get_notification_config(environment)
if environment == "development"
return (
channel = "dev-testing",
topic = "Development Tests",
frequency = :verbose # More frequent updates
)
elseif environment == "production"
return (
channel = "production-alerts",
topic = "Production Runs",
frequency = :important # Only critical updates
)
else
return (
channel = "research",
topic = "Analysis Results",
frequency = :normal
)
end
end
# Team-specific channel routing
function route_to_team_channels(message_type, content)
routing = Dict(
:error => ("errors", "System Errors"),
:progress => ("progress", "Task Updates"),
:results => ("results", "Analysis Results"),
:publication => ("publications", "Paper Work"),
:backup => ("backups", "System Maintenance")
)
channel, topic = routing[message_type]
notifyme(content,
zulip_channel=channel,
zulip_topic=topic)
end
๐ Integration Patterns
With External Tools
# Integration with job schedulers (SLURM, PBS, etc.)
function slurm_job_notification(job_id, status, details="")
topic = "HPC Jobs - $(Dates.format(now(), \"yyyy-mm\"))"
status_emoji = Dict(
"RUNNING" => "๐",
"COMPLETED" => "โ
",
"FAILED" => "โ",
"CANCELLED" => "๐",
"TIMEOUT" => "โฐ"
)[status]
notifyme("$status_emoji **SLURM Job $status**\\n\\n" *
"โข Job ID: $job_id\\n" *
"โข Status: $status\\n" *
"$details",
zulip_channel="hpc-jobs",
zulip_topic=topic)
end
# Integration with Git workflows
function git_analysis_complete(commit_hash, analysis_results)
notifyme("๐ฌ **Analysis complete for commit $(commit_hash[1:8])**\\n\\n" *
"โข Commit: $commit_hash\\n" *
"โข Results: $(analysis_results.summary)\\n" *
"โข Plots generated: $(length(analysis_results.plots))\\n\\n" *
"Ready for code review and integration",
attachments=analysis_results.plots,
zulip_channel="code-analysis",
zulip_topic="Automated Analysis Results")
end
Next Steps:
- Copy relevant templates to your workflow
- Customize channel and topic names for your team
- Test templates with simple examples first
- Adapt message formatting to your preferences
- Set up appropriate error handling for your use cases
See also:
- Setup Guide - Channel creation and bot configuration
- Advanced Features - Progress tracking and exception handling
- Examples - More real-world research examples