Convert coauthor and affiliation signals into profile heat maps.
(scholar_profile: Dict[str, Any])
| 1324 | |
| 1325 | |
| 1326 | def _build_scholar_heat_maps(scholar_profile: Dict[str, Any]) -> Dict[str, Dict[str, float]]: |
| 1327 | """Convert coauthor and affiliation signals into profile heat maps.""" |
| 1328 | author_heat: Dict[str, float] = {} |
| 1329 | institution_heat: Dict[str, float] = {} |
| 1330 | |
| 1331 | network_entries = scholar_profile.get("collaboration_network") or scholar_profile.get("top_coauthors") or [] |
| 1332 | for index, entry in enumerate(network_entries): |
| 1333 | name = _collapse_whitespace(entry.get("name", "")) |
| 1334 | count = int(entry.get("count") or 0) |
| 1335 | citation_sum = int(entry.get("citation_sum") or 0) |
| 1336 | last_year = int(entry.get("last_year") or 0) |
| 1337 | if not name or count <= 0: |
| 1338 | continue |
| 1339 | recent_bonus = 0.03 if last_year and last_year >= datetime.now().year - 1 else 0.0 |
| 1340 | citation_bonus = min(0.12, citation_sum / 800.0) |
| 1341 | seeded = min(0.82, 0.18 + 0.07 * count + citation_bonus + recent_bonus - 0.015 * index) |
| 1342 | author_heat[name] = round(max(0.15, seeded), 4) |
| 1343 | |
| 1344 | affiliation = _collapse_whitespace(scholar_profile.get("affiliation", "")) |
| 1345 | if affiliation: |
| 1346 | institution_heat[affiliation] = 0.6 |
| 1347 | |
| 1348 | return { |
| 1349 | "author_heat": author_heat, |
| 1350 | "institution_heat": institution_heat, |
| 1351 | } |
| 1352 | |
| 1353 | |
| 1354 | def parse_google_scholar_profile(scholar_url: str, use_llm: bool = True) -> Dict[str, Any]: |
no test coverage detected