Fixes #12 - Add more descriptive email body - #14
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses #12 by generating a more descriptive, data-driven email body for the Lambda’s causal analysis results, and adds a small metadata payload to the analysis output so downstream reporting/messaging can describe “insufficient data” scenarios more clearly.
Changes:
- Add
build_email_body()and switch outbound emails to use the dynamically generated body. - Add
_metadatatorun_causal_analysis()results (experiment/hyperparameter counts + insufficient-data flags/reasons). - Update report generation and recommendation loops to ignore the
_metadataentry; remove the old static email-body constant.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
lambda_function.py |
Adds build_email_body() and skips _metadata when iterating analysis groups; uses new email body in send_email(). |
helper_services/report_helper.py |
Excludes _metadata when deciding whether there are any analysis groups and when iterating groups for the PDF. |
helper_services/causal_analysis_helper.py |
Tracks experiment count and appends a _metadata block describing insufficient-data conditions. |
common/common_constants.py |
Removes the unused CAUSAL_ANALYSIS_EMAIL_BODY constant. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR addresses #12 by making the results email body more informative, using newly added causal-analysis metadata to summarize experiment counts, filters, and (when available) top causal effects.
Changes:
- Added a dynamic
build_email_body(...)for richer plain-text email content. - Extended
run_causal_analysis(...)to include a reserved_metadataentry (experiment/hyperparameter counts + insufficient-data flags/reason). - Updated report generation and recommendations iteration to ignore
_metadata; removed the old constant email body.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
lambda_function.py |
Builds a descriptive email body from analysis results and skips _metadata when iterating groups. |
helper_services/report_helper.py |
Excludes _metadata from report “analysis groups” rendering. |
helper_services/causal_analysis_helper.py |
Adds _metadata with experiment counts and insufficient-data details. |
common/common_constants.py |
Removes the static CAUSAL_ANALYSIS_EMAIL_BODY constant. |
.gitignore |
Ignores .claude/*. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Replace isnan check with isfinite to block inf values in email body
- Add isfinite guard before adding effects to recommendation dimensions
- Track load_error in except block; check it before raw_df.empty to
avoid misattributing exceptions as "no data downloaded"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| all_effects = {} | ||
| for group, group_data in causal_analysis_results.items(): | ||
| if group == "_metadata": | ||
| continue | ||
| for k, v in group_data.get("effects", {}).items(): | ||
| if isinstance(v, (int, float)) and math.isfinite(v): | ||
| all_effects[k] = v | ||
|
|
||
| if all_effects: | ||
| sorted_effects = sorted(all_effects.items(), key=lambda x: abs(x[1]), reverse=True)[:3] | ||
| lines.append("Top causal effects:") | ||
| for hp, effect in sorted_effects: | ||
| hp_name = hp.split(".", 1)[1] if "." in hp else hp | ||
| sign = "+" if effect >= 0 else "" | ||
| lines.append(f" {hp_name}: {sign}{effect:.4f}") | ||
|
|
| sign = "+" if effect >= 0 else "" | ||
| lines.append(f" {hp_name}: {sign}{effect:.4f}") |
| insufficient_data_reason = f"Error loading data: {load_error}" | ||
| elif raw_df.empty: | ||
| insufficient_data = True | ||
| insufficient_data_reason = "No data files could be downloaded from provided URLs" |
No description provided.