A biology-based quality-diversity algorithm for drug repurposing in Alzheimer's disease using automated machine learning.
The 7 matches
- [1] § Methods › Biologically-informed feature representation with GNNs ↔ 1_embeddings/example_train_drugs.py, lines 1 to 32 · score 0.71 · GraphSAGE, AlzKB, drug embeddings, gene embeddings, VGAE, modeling · Report a mismatch
- [2] § Methods › Biologically-informed feature representation with GNNs ↔ 1_embeddings/example_train_genes.py, lines 1 to 26 · score 0.69 · GraphSAGE, AlzKB, gene embeddings, drug embeddings, VGAE · Report a mismatch
- [3] § Methods › Biologically-informed feature representation with GNNs ↔ 4_analysis/validate_atc.py, lines 23 to 137 · score 0.65 · Euclidean distance, ATC, inter, embedding space, intra, validate · Report a mismatch
- [4] § Methods › Biologically-informed feature representation with GNNs ↔ 3_visualization/plot_figure1_umap.py, lines 41 to 98 · score 0.64 · UMAP visualization, AD genes, background, neighborhoods, topological, modules · Report a mismatch
- [5] § Methods › Biologically-informed feature representation with GNNs ↔ 1_embeddings/example_train_drugs.py, lines 203 to 236 · score 0.61 · clustering loss, AD drugs, encourages, pairwise, training, objective · Report a mismatch
- [6] § Methods › TPOT2 with MAP-Elites for AutoML-driven drug classification › Optimization-driven conditional data partitioning › Tree-structured parzen estimator (TPE) optimization ↔ 2_TPOT2+MapElites/run_XGBoost.py, lines 16 to 109 · score 0.57 · random seed, search space, hyperparameter, probability, objective, optimized · Report a mismatch
- [7] § Methods › TPOT2 with MAP-Elites for AutoML-driven drug classification ↔ 2_TPOT2+MapElites/run_MAP_Elites_Seed.py, lines 172 to 222 · score 0.53 · search space, MAP Elites, survival, TPOT2, parent, population · Report a mismatch
Paper
Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 260 lines · 8.4 KB · no license · 2 matches
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- Script: example_train_drugs.py
- Author: Sisi Shao
- [NOTE FOR REPRODUCIBILITY]
- This script demonstrates the drug embedding training pipeline used in the study.
- It builds a Drug–Gene bipartite subgraph and trains a VGAE model to obtain node
- embeddings. The exported embeddings are restricted to Drug nodes.
- As described in the manuscript:
- - Gene embeddings are derived from GraphSAGE in a separate script.
- - Drug embeddings are derived from VGAE (this script).
- [DATABASE NOTE]
- The original study used Neo4j. The current AlzKB backend has migrated to Memgraph.
- This script uses the standard Bolt protocol and is compatible with both.
- [SCALABILITY NOTE]
- This is an example script. It intentionally uses identity features (one-hot) and
- simple edge reconstruction. For large graphs, consider using real node features
- and/or negative sampling / minibatch training.
- """
- import sys
- import torch
- import pandas as pd
- import torch.nn.functional as F
- from torch_geometric.data import Data
- from torch_geometric.nn import VGAE, GCNConv
- from neo4j import GraphDatabase
- # ============================
- # 1. CONFIGURATION
- # ============================
- NEO4J_URI = "neo4j+s://neo4j.alzkb.ai:7687"
- # Demo subset for speed. Replace with your full list if you want the full demo.
- TARGET_AD_GENE_IDS = [
- 1, 9, 15, 19, 20, 28, 42, 45, 46, 47, 48, 49,
- 32764, 32765
- ]
- OUT_CHANNELS = 16
- EPOCHS = 50
- LR = 0.01
- BETA_KL = 1.0 # weight on KL term (kept standard)
- BETA_CLUSTER = 1.0 # weight on clustering term
- OUT_CSV = "embeddings_drug_vgae_ADcluster.csv"
- # ============================
- # 2. DATABASE CONNECTION
- # ============================
- class LoadGraph:
- def __init__(self, uri: str):
- try:
- self.driver = GraphDatabase.driver(uri, auth=None)
- self.driver.verify_connectivity()
- print("Connected to Graph Database.")
- except Exception as e:
- print(f"Database connection failed: {e}")
- self.driver = None
- def close(self):
- if self.driver:
- self.driver.close()
- def run_cypher(self, query: str):
- if not self.driver:
- return None
- with self.driver.session() as session:
- try:
- return session.run(query).data()
- except Exception as e:
- print(f"Query error: {e}")
- return None
- # ============================
- # 3. LOAD DRUG–GENE GRAPH
- # ============================
- alzkb = LoadGraph(NEO4J_URI)
- # Drug–Gene edges restricted to (protein-coding) genes in the target list (demo-style).
- drug_gene_query = f"""
- MATCH (a:Drug)--(g:Gene)
- WHERE g.typeOfGene = 'protein-coding' AND ID(g) IN {TARGET_AD_GENE_IDS}
- RETURN DISTINCT ID(a) AS drug_id, ID(g) AS gene_id, a.commonName AS drug_name
- """
- # Drugs directly connected to Alzheimer's Disease concept node (used for clustering target).
- alz_drug_query = """
- MATCH (a:Drug)-[]-(b {commonName:"Alzheimer's Disease"})
- RETURN DISTINCT ID(a) AS drug_id, a.commonName AS drug_name, a.xrefDrugbank AS drugbank
- """
- drug_gene_data = alzkb.run_cypher(drug_gene_query)
- alz_drug_data = alzkb.run_cypher(alz_drug_query)
- alzkb.close()
- if not drug_gene_data:
- print("No Drug–Gene edges found for the given target genes. Exiting.")
- sys.exit(0)
- # Collect node IDs (original DB IDs)
- drug_ids = sorted({row["drug_id"] for row in drug_gene_data if row.get("drug_id") is not None})
- gene_ids = sorted({row["gene_id"] for row in drug_gene_data if row.get("gene_id") is not None})
- if len(drug_ids) == 0 or len(gene_ids) == 0:
- print("Insufficient nodes (no drugs or no genes) after filtering. Exiting.")
- sys.exit(0)
- # Build a unified node index mapping (drugs + genes)
- all_node_ids = drug_ids + gene_ids
- node_id_to_idx = {nid: i for i, nid in enumerate(all_node_ids)}
- idx_to_node_id = {i: nid for nid, i in node_id_to_idx.items()}
- # Drug names map (best-effort, may have duplicates; we keep first)
- drug_name_map = {}
- for row in drug_gene_data:
- did = row.get("drug_id")
- dname = row.get("drug_name")
- if did is not None and did not in drug_name_map and dname is not None:
- drug_name_map[did] = dname
- # Build edges (Drug -> Gene) as an undirected set for VGAE reconstruction stability
- # (You can keep directed if desired, but undirected is common for VGAE demos.)
- edges = []
- for row in drug_gene_data:
- did = row["drug_id"]
- gid = row["gene_id"]
- if did in node_id_to_idx and gid in node_id_to_idx:
- u = node_id_to_idx[did]
- v = node_id_to_idx[gid]
- edges.append((u, v))
- edges.append((v, u)) # make symmetric
- edge_index = torch.tensor(edges, dtype=torch.long).t().contiguous()
- if edge_index.numel() == 0:
- print("No edges found after processing. Exiting.")
- sys.exit(0)
- num_nodes = len(all_node_ids)
- # Identity features (demo). For large graphs, replace with meaningful features.
- x = torch.eye(num_nodes, dtype=torch.float32)
- data = Data(x=x, edge_index=edge_index)
- # Identify which indices correspond to drugs
- is_drug = torch.zeros(num_nodes, dtype=torch.bool)
- for did in drug_ids:
- is_drug[node_id_to_idx[did]] = True
- # AD-drug indices for clustering target (best-effort intersection)
- alz_drug_ids = []
- alz_drug_name_map = {}
- if alz_drug_data:
- for row in alz_drug_data:
- did = row.get("drug_id")
- if did is not None:
- alz_drug_ids.append(did)
- dname = row.get("drug_name")
- if did is not None and dname is not None:
- alz_drug_name_map[did] = dname
- alz_drug_ids = sorted(set(alz_drug_ids))
- alz_drug_idx = [node_id_to_idx[did] for did in alz_drug_ids if did in node_id_to_idx]
- alz_drug_idx_tensor = torch.tensor(alz_drug_idx, dtype=torch.long)
- print(f"Loaded nodes: {num_nodes} (drugs={len(drug_ids)}, genes={len(gene_ids)})")
- print(f"Loaded edges (symmetrized): {data.edge_index.size(1)}")
- print(f"AD drugs (for clustering): {len(alz_drug_idx)}")
- # ============================
- # 4. VGAE MODEL
- # ============================
- class Encoder(torch.nn.Module):
- def __init__(self, in_channels: int, out_channels: int):
- super().__init__()
- self.conv1 = GCNConv(in_channels, 2 * out_channels, cached=True)
- self.conv_mu = GCNConv(2 * out_channels, out_channels, cached=True)
- self.conv_logstd = GCNConv(2 * out_channels, out_channels, cached=True)
- def forward(self, x, edge_index):
- h = torch.relu(self.conv1(x, edge_index))
- return self.conv_mu(h, edge_index), self.conv_logstd(h, edge_index)
- encoder = Encoder(data.num_node_features, OUT_CHANNELS)
- model = VGAE(encoder)
- optimizer = torch.optim.Adam(model.parameters(), lr=LR)
- # ============================
- # 5. TRAINING LOOP
- # ============================
- model.train()
- print("Starting Drug VGAE training...")
- for epoch in range(EPOCHS):
- optimizer.zero_grad()
- z = model.encode(data.x, data.edge_index)
- # Standard VGAE objective
- loss_recon = model.recon_loss(z, data.edge_index)
- loss_kl = (1.0 / data.num_nodes) * model.kl_loss()
- # Clustering loss: encourage AD drugs to be close (if we have enough)
- if len(alz_drug_idx) > 1:
- alz_emb = z[alz_drug_idx_tensor]
- pairwise_dist = F.pairwise_distance(
- alz_emb.unsqueeze(1),
- alz_emb.unsqueeze(0),
- p=2
- )
- loss_cluster = torch.mean(torch.max(pairwise_dist, dim=1)[0])
- else:
- loss_cluster = torch.tensor(0.0)
- loss = loss_recon + (BETA_KL * loss_kl) + (BETA_CLUSTER * loss_cluster)
- loss.backward()
- optimizer.step()
- if epoch % 10 == 0 or epoch == EPOCHS - 1:
- print(
- f"Epoch {epoch:03d} | "
- f"recon={loss_recon.item():.4f} | kl={loss_kl.item():.4f} | "
- f"cluster={float(loss_cluster):.4f} | total={loss.item():.4f}"
- )
- # ============================
- # 6. EXPORT DRUG EMBEDDINGS
- # ============================
- model.eval()
- with torch.no_grad():
- z = model.encode(data.x, data.edge_index)
- # Export only drug nodes, in strict index order
- drug_rows = []
- for idx in range(num_nodes):
- if not bool(is_drug[idx]):
- continue
- node_id = idx_to_node_id[idx] # original DB ID
- name = drug_name_map.get(node_id) or alz_drug_name_map.get(node_id) or ""
- emb = z[idx].cpu().numpy().tolist()
- drug_rows.append([node_id, name] + emb)
- cols = ["node_id", "drug"] + [f"embedding_{i}" for i in range(OUT_CHANNELS)]
- embeddings_df = pd.DataFrame(drug_rows, columns=cols)
- embeddings_df.to_csv(OUT_CSV, index=False)
- print(f"Saved drug embeddings to {OUT_CSV}")
example_train_drugs.py at commit ecc88ce, no license · at the source
Overview
- Department of Biostatistics, Fielding School of Public Health, University of California,Los Angeles, CA USA
- Department of Computational Biomedicine, Cedars-Sinai Medical Center,Los Angeles, CA USA
- Department of Genetics, University of Pennsylvania,Philadelphia, PA USA
- Institute for Biomedical Informatics, University of Pennsylvania,Philadelphia, PA USA
- Division of Informatics, Department of Biostatistics, Epidemiology and Informatics, University of Pennsylvania,Philadelphia, PA USA
Abstract
Background: Alzheimer’s disease (AD) remains a major therapeutic challenge, characterized by high clinical trial failure rates and limited efficacy of current treatments. Drug repurposing offers a faster, lower-risk route to new therapies; however, existing computational approaches often prioritize predictive accuracy over mechanistic novelty and interpretability, both of which are critical for clinical translation.
Results: We introduce a quality-diversity Automated Machine Learning (AutoML) framework that integrates biologically informed graph neural network (GNN) embeddings with a MAP-Elites-guided search to discover predictive yet mechanistically distinct therapeutic hypotheses. Drugs and genes are embedded using GraphSAGE and variational graph autoencoders trained on the Alzheimer’s Knowledge Base (AlzKB), with a clustering loss used to anchor known AD entities and define dimensions of biological novelty. In an AD case study using matched ADSP GWAS-derived features, our framework successfully recovered known drug–gene relationships and identified robust consensus candidates across independent validation runs. Most notably, the search consistently prioritized Triclosan—a recently identified environmental risk factor for AD neuroinflammation—and the Ketamine/
Conclusions: Beyond AD, this framework offers a generalizable strategy for integrating biomedical knowledge graphs with diversity-enhancing AutoML to accelerate the discovery of mechanistically novel drug candidates across complex polygenic diseases.
Supplementary information: The online version contains supplementary material available at 10.1186/
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 7 matches between paragraphs and lines of code.
SisiShao/Alzheimer-Drug-Repurposing-MAP-Elites
ecc88ce824c3b4b966d2b0781a0f8565527d454b, 11 January 2026Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
12 files
- 1_embeddings/
example_train_drugs.py , Python, 260 lines, 2 matches - 1_embeddings/
example_train_genes.py , Python, 196 lines, 1 match - 2_TPOT2+MapElites/
mapelites.py , Python, 106 lines - 2_TPOT2+MapElites/
run_MAP_Elites_Seed.py , Python, 318 lines, 1 match - 2_TPOT2+MapElites/
run_TPOT_NSGA2.py , Python, 216 lines - 2_TPOT2+MapElites/
run_XGBoost.py , Python, 112 lines, 1 match - 3_visualization/
plot_figure1_umap.py , Python, 102 lines, 1 match - 4_analysis/
calc_stats_map_elites.py , Python, 98 lines - 4_analysis/
calc_stats_nsga2.py , Python, 94 lines - 4_analysis/
calc_stats_xgboost.py , Python, 66 lines - 4_analysis/
validate_atc.py , Python, 141 lines, 1 match - README.md, Text, 226 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 11 scripts, each with its path and the digest of its content;
- 7 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Data availability
The genomic datasets supporting the conclusions of this article are available in the NIAGADS repository under controlled access (Alzheimer's Disease Sequencing Project; NG00067, Version 18; http://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 30 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 8 authors, 6 keywords, 2 funders, 22 references.
Cite
This paper
Shao, S., Ribeiro, P. H., Orlenko, A., Cardone, K. M., Ramirez, C. M., Shen, L., Ritchie, M. D., & Moore, J. H. (2026). A biology-based quality-diversity algorithm for drug repurposing in Alzheimer's disease using automated machine learning. BioData mining, 19(1), 34. https://
BibTeX
@article{shao2026biology
author = {Shao, Sisi and Ribeiro, Pedro Henrique and Orlenko, Alena and Cardone, Katie M. and Ramirez, Christina M. and Shen, Li and Ritchie, Marylyn D. and Moore, Jason H.},
title = {{A biology-based quality-diversity algorithm for drug repurposing in Alzheimer's disease using automated machine learning}},
journal = {BioData mining},
year = {2026},
month = mar,
volume = {19},
number = {1},
pages = {34},
publisher = {BMC},
issn = {1756-0381},
doi = {10.1186/
url = {https://
pmid = {41913218},
pmcid = {PMC13159293}
}
RIS
TY - JOUR
AU - Shao, Sisi
AU - Ribeiro, Pedro Henrique
AU - Orlenko, Alena
AU - Cardone, Katie M.
AU - Ramirez, Christina M.
AU - Shen, Li
AU - Ritchie, Marylyn D.
AU - Moore, Jason H.
TI - A biology-based quality-diversity algorithm for drug repurposing in Alzheimer's disease using automated machine learning
T2 - BioData mining
J2 - BioData Min
PY - 2026
DA - 2026/
VL - 19
IS - 1
SP - 34
SN - 1756-0381
PB - BMC
DO - 10.1186/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1186/
"type": "article-journal",
"title": "A biology-based quality-diversity algorithm for drug repurposing in Alzheimer's disease using automated machine learning",
"container-title": "BioData mining",
"author": [
{
"family": "Shao",
"given": "Sisi"
},
{
"family": "Ribeiro",
"given": "Pedro Henrique"
},
{
"family": "Orlenko",
"given": "Alena"
},
{
"family": "Cardone",
"given": "Katie M."
},
{
"family": "Ramirez",
"given": "Christina M."
},
{
"family": "Shen",
"given": "Li"
},
{
"family": "Ritchie",
"given": "Marylyn D."
},
{
"family": "Moore",
"given": "Jason H."
}
],
"container-title-short":
"volume": "19",
"issue": "1",
"page": "34",
"DOI": "10.1186/
"PMID": "41913218",
"PMCID": "PMC13159293",
"ISSN": "1756-0381",
"publisher": "BMC",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
30
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1038/s41467-025-57027-x [code]
- Topological identification and interpretation for single-cell epigenetic regulation elucidation in multi-tasks using scAGDE.Journal: Nature communicationsIn common: PyTorch Geometric, XGBoost, UMAP, 7 other tools
- [2] doi:10.1186/s12864-025-11946-7 [code]
- GNODEVAE: a graph-based ODE-VAE enhances clustering for single-cell data.Journal: BMC genomicsIn common: PyTorch Geometric, UMAP, PyTorch, 6 other tools, 1 reference
- [3] doi:10.1126/sciadv.adz9283 [code]
- AI-driven discovery of dual antiaging and anti-AD therapeutics via PROTAC target deconvolution of a super-enhancer-regulated
axis. Journal: Science advancesIn common: PyTorch Geometric, XGBoost, PyTorch, 6 other tools, Alzheimer's / dementia - [4] doi:10.1093/bib/bbag118 [code]
- Drug screening for α-synuclein aggregation inhibitors via multimodal graph neural network.Journal: Briefings in bioinformaticsIn common: PyTorch Geometric, XGBoost, PyTorch, 6 other tools
- [5] doi:10.1038/s41597-025-06474-8 [code]
- Fatigue Characterization Multimodal Datasets for Stereo Vision in Mixed Reality.Journal: Scientific dataIn common: PyTorch Geometric, XGBoost, PyTorch, 6 other tools
- [6] doi:10.1186/s12916-025-04405-3 [code]
- Exploring synthetic controls in rare diseases with a proof of concept in spinal cord injury.Journal: BMC medicineIn common: PyTorch Geometric, XGBoost, PyTorch, 6 other tools
- [7] doi:10.1007/s13534-025-00462-y [code]
- Automatic prediction of stroke treatment outcomes: latest advances and perspectives.Journal: Biomedical engineering lettersIn common: PyTorch Geometric, XGBoost, PyTorch, 6 other tools
- [8] doi:10.1093/nar/gkag706 [code]
- scDifformer: diffusion-based post-training for virtual cell modeling across large-scale single-cell data.Journal: Nucleic acids researchIn common: PyTorch Geometric, UMAP, PyTorch, 6 other tools
- [9] doi:10.21203/rs.3.rs-9676637/v1 [code]
- A Comprehensive Benchmarking of Spatial Deconvolution and Domain Detection Methods across Diverse Tissues and Spatial Transcriptomic TechnologiesJournal: Research Square (preprint)In common: PyTorch Geometric, UMAP, PyTorch, 6 other tools
- [10] doi:10.1016/j.isci.2026.116055 [code]
- Mapping the transcriptional diversity of calcium signaling in the mouse and human brain.Journal: iScienceIn common: PyTorch Geometric, UMAP, PyTorch, 6 other tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 11 scripts, and 7 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:97bb47c70ed86690…
Add the badge to the code's README
If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.
Markdown
<!-- oscr-badge:start -->
[](https://openscicode.org/badge/doi/10.1186/s13040-026-00550-4)
<!-- oscr-badge:end -->reStructuredText
.. oscr-badge:start
.. image:: https://openscicode.org/badge/doi/10.1186/s13040-026-00550-4.svg
:target: https://openscicode.org/badge/doi/10.1186/s13040-026-00550-4
:alt: OSCR
.. oscr-badge:endHTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1186/s13040-026-00550-4"><img src="https://openscicode.org/badge/doi/10.1186/s13040-026-00550-4.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".
If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.
Report a mismatch between the code and the paper · Report a code error (signed in)
Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.
Report a reproduction failure (signed in)
Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
