Materials Science ยท Personal Infrastructure Project ยท Stage 1
A complete research infrastructure โ composition calculator, literature cross-checking against three independent public databases, and multi-instrument characterization import โ built to replace years of scattered spreadsheets and a genuinely messy desktop research folder.
Background
As a materials researcher working on novel alloys, my experimental results were scattered across spreadsheets, Origin project files, raw instrument output, and โ if I'm honest โ a genuinely messy desktop folder accumulated over years. Two things motivated building a proper system, in roughly equal measure.
One place to record what was made, how, and what it measured โ usable later as training data for machine learning.
Could this be built solo? And could the desktop folder finally be tamed after years of neglect? Both turned out to matter as much as the practical goal.
Workflow
The system was built to directly support this routine โ not to replace it.
Engineering
The original design sketch was considerably more ambitious than what actually shipped โ a full Docker Compose stack with MinIO/S3 object storage, Redis caching, a Jupyter analysis environment, and a file-watcher service auto-ingesting instrument output. Real use quickly showed that a leaner system โ Postgres, a Python API layer, and a proper desktop interface โ covered everything actually needed, without the operational overhead of running five services to enter one sample.
Knowing what to cut turned out to matter more than the original breadth of the plan. Every sample's full story โ composition, how it was made, and what it measured โ still stays connected, just through a considerably simpler path than first imagined.
Screenshot: Docker containers running
alloy_lab โโโ samples composition (JSONB), lineage, VEC/ฮด/ฮH_mix โโโ synthesis method, temperature, atmosphere, duration โโโ characterization one row per XRD/VSM/SEM measurement โโโ properties extracted numeric results per measurement โโโ literature_checks deduped matches from 3 external databases โโโ material_classes
Tooling
Type a formula. Get exactly what to weigh.
This was, by a wide margin, the most-iterated part of the whole
project. Every feature that looked simple at first revealed a real
edge case once tested against actual formulas โ most memorably,
distinguishing a genuine typo from valid chemistry: Cp
looks like a mistake, but is actually two real, valid one-letter
elements (C and P) run together. There's no purely syntactic way to
know which was intended, so the parser now requires an explicit
number after every element and raises a clear error on anything
ambiguous, rather than silently guessing.
Fe65Nd30Co5 โ 10 g target Fe 4.40 g Nd 5.24 g Co 0.36 g
Screenshot: Updated New Entry tab, with options to calculate from a pre-alloy, synthesis feasibility check and skip literature checks
Physics
Before any melting: four composition-only numbers, computed instantly, no lab work required.
Predicts likely crystal structure โ solid solution type (BCC / FCC).
Small ฮด favors a solid solution; large ฮด favors intermetallic phases.
Predicts compound-forming tendency between elements.
A different question from the other three: not "will this form a solid solution," but "can this even be melted together" โ using each element's melting and boiling point.
The insight behind the fourth check: melting-point spread alone isn't the right signal. What actually matters is whether homogenizing the melt requires heating past the boiling point of the most volatile constituent โ at that point, the element doesn't just risk some evaporation, it boils away before the alloy can homogenize. Three tiers, deliberately not collapsed into one confidence level: a hard physical block (suggests mechanical alloying or sintering instead), a flagged "genuinely uncertain" zone (pure composition data isn't sufficient โ check literature or run a small test melt), and a comfortable "no concern" case.
| Example composition | Result | Why |
|---|---|---|
| W + Mg | ๐ซ Blocked | Melting W (3695 K) is far above Mg's boiling point (1363 K) |
| Fe + Nb | โ ๏ธ Caution | Only 384 K margin โ pure-element numbers alone can't call this either way |
| Fe + Co + Ni | โ OK | Comfortable margin, no volatility concern |
Cross-Validation
Every composition is checked against three independent public materials databases.
Two fully independent databases (Materials Project and OQMD) agreed on a compound's stability within 0.001 eV/atom โ strong cross-validation that the result reflects real physics, not one group's specific settings.
Databases used: Materials Project ยท OQMD ยท Alexandria
A fourth database (AFLOW) was evaluated and deliberately dropped after hitting an unmaintained client library, a dead API endpoint, and unresolved query-semantics ambiguity โ three independent reasons was enough to redirect effort toward Alexandria instead, which turned out to be the stronger choice regardless.
Instruments
Real characterization data now flows directly into the database โ no manual transcription.
| Sample | XRD peaks | Lattice a (ร ) |
|---|---|---|
| RP1a | 101 | 15.627 |
| RP2a | 96 | 15.630 |
| RP3a | 98 | 15.744 |
| VSM property (sample RP1a) | Value |
|---|---|
| Saturation moment (Ms) | 6.883 emu |
| Remanence (Mr) | โ0.024 emu |
| Coercivity (Hc) | 198.6 Oe |
| Ms per gram | 137.65 emu/g |
The VSM pipeline caught a genuine data-quality problem, not just a code bug: the instrument's own recorded sample mass was an obviously wrong placeholder value, with the real mass only available encoded in the filename. Normalizing by the wrong mass would have silently corrupted every derived magnetic property โ the fix was parsing mass from the filename convention instead of trusting the instrument's own metadata field.
Screenshot: XRD pattern and VSM hysteresis loop rendered in the Data Viewer
The instrument (Zeiss) stores its real metadata inside proprietary compressed binary TIFF tags rather than standard fields โ a custom binary string-extraction routine was needed to recover magnification, accelerating voltage, working distance, and detector channel.
Importing 690 real SEM files one at a time was correct but slow โ 5โ10 minutes for the full set. Solved with batch import, without touching the parser itself.
| SEM metadata (example) | Value |
|---|---|
| Magnification | 1.00 KX |
| EHT (voltage) | 10.00 kV |
| Working distance | 7.1 mm |
| Pixel size | 277.3 nm |
| Detector | SE2 / InLens |
Interface
Everything above, in one application โ not a collection of scripts.
Screenshot: New Entry tab, and the three literature database selectors with common cutoff slider
Screenshot: Data import interface โ XRD, VSM, and SEM characterization data imported directly into the database
Screenshot: SEM image viewer โ fast visualization of SEM images directly in the application
Screenshot: Metabase dashboard โ browsing the database without writing SQL
Retrospective
A hardcoded password was found and "fixed" once, then found again as a commented-out leftover copy. Grepping for a secret isn't done until it returns nothing at all, comments included.
A fourth literature database (AFLOW) was abandoned after three independent red flags โ an unmaintained library, a dead endpoint, unresolved query semantics. Stopping was the correct call, not a failure to push through.
Both the VSM sample-mass field and the SEM binary tags looked like reliable structured data. Neither was, in different ways โ worth verifying, not assuming.
A dedup-logic regression shipped because the fix was verified in isolation rather than through the actual full call chain it belonged to. Caught only by running it for real.
Prototyping in one virtual environment and integrating in
another is an easy way to get a clean import error later โ worth
checking pip list in the venv that will actually run
the script.
A standalone sorter utility, tested against the real multi-year desktop folder, correctly routed hundreds of files โ XRD, ICP, Origin projects โ into organized subfolders in one pass. The second motivation for this project, resolved.
Two XRD peaks looked like a textbook Kฮฑ1/Kฮฑ2 instrumental doublet โ their positions matched the predicted split to within 0.1ยฐ. But their independently-fit intensity ratio was ~1.1, not the physically fixed ~0.5 the real effect requires. A second, independent check caught what position matching alone would have called a confirmed doublet โ more likely a real crystallographic feature instead.
A large folder of raw data (and, more importantly, some unpublished drafts) turned out to still be fully committed to git โ even though it was correctly listed in .gitignore. Adding a rule only stops new files from being tracked; it does nothing for files already committed before the rule existed. Caught and fixed with a full history rewrite before the repository stayed public.
Status
Resources
Here you can download the presentation of the project in pdf format :