Inspiration
One of us studied tardigrades in high school and kept coming back to one question: how does an animal smaller than a grain of sand lose almost all of its water, stay dried out for years, and then recover? This weekend we revisited that question with machine learning.
Tardigrades survive drying out because of a few protein families: CAHS proteins in tardigrades, and LEA proteins and dehydrins in plants. As a cell dries, these proteins turn its interior into a glass-like state instead of letting it crystallize.
That has practical value. Vaccines, clotting factors and lab reagents need to be kept cold, and the cold chain is often what fails where medicine is needed most. Proteins that protect other molecules from drying out are a lead for storing these without refrigeration. There are millions of known protein sequences, though, and a lab can only test a few. We wanted to build a first-pass filter.
What it does
AnHydra (anhydra.work) takes an amino-acid sequence and reports whether it resembles the desiccation-protective protein families, and why.
For each sequence it shows:
- a family score from a protein language model
- the closest known protective proteins in our reference set
- the biophysical features that raised or lowered the score
- a plain-language explanation generated by Gemini
AnHydra is a triage tool, not an efficacy predictor. It answers "does this look like the protective families?", not "how well will this protect?". If the model can't produce a score, the site returns an error rather than a placeholder number.
How we built it
- Data: Protective proteins from UniProt vs. other intrinsically disordered proteins, matched on length and disorder
- Embed: Meta's ESM-2 protein language model (frozen) turns each sequence into a 480-number vector
- Model: A linear classifier on that vector, plus an interpretable biophysical model for the explanation
- Evaluate: Cluster-split cross-validation against a BLAST baseline
- Ship: FastAPI and Caddy on Vultr, at anhydra.work
ESM-2 reads a protein and produces one vector per residue. We average those into a single 480-number embedding and train a classifier on top of it: the probability that a sequence is protective is the sigmoid of a weighted sum of the embedding plus a bias. ESM-2's weights stay fixed; only the classifier's weights and bias are trained. We also trained a DeepFam-style CNN from scratch for comparison.
To keep the evaluation honest, we clustered proteins with CD-HIT at 40% identity and kept each cluster entirely in training or entirely in testing, so near-identical proteins never appear on both sides.
Stack: Python, PyTorch, scikit-learn, ESM-2, BLAST, FastAPI, React, Gemini API, Auth0 (Google and approved .edu sign-in, with PostgreSQL accounts), Caddy, and Vultr. The domain, anhydra.work, is a GoDaddy Registry .work domain.
Challenges we ran into
Slow iterations. Embedding thousands of sequences with ESM-2 and training on them is slow on CPU. Each iteration took several hours before we could check whether it worked, so a single mistake in the data could cost us several hours of precious hackathon time. We reduced the risk where we could:
- the embedding run saves progress every 256 sequences, so a dropped connection or reboot doesn't lose hours of work
- embeddings are cached by sequence, so when we rebuilt the dataset only the new sequences needed embedding
- we stopped the training code from re-reading the full embedding cache for every sequence
A result that was too good. On the task we designed to be hard, the model scored an AUC of 0.987, when we expected 0.7 to 0.8. We investigated before trusting it:
- With shuffled labels, the model scored about 0.50, which is chance. The validation setup was working.
- Length alone scored 0.770. After matching lengths, it dropped to 0.514 while ESM-2 stayed at 0.990, so length wasn't the explanation.
- The actual cause was our negative set. It came from DisProt, which labels disordered regions within proteins, not fully disordered proteins. Only 447 of 1,604 negatives were at least 30% disordered, so the "hard" task was mostly comparing folded and unfolded proteins.
We rebuilt the negatives from UniProt as fully disordered, non-protective proteins matched on length and disorder, and reran everything. Given how long each run took, this was an expensive decision, but the original number wasn't one we could defend.
Coordination. Four people working in one repository for 36 hours meant merge conflicts, two parallel frontends, and an authentication setup where Auth0, the frontend and the backend all had to agree on the same token format. We split the work into clear areas (data, backend, frontend, deployment) and pulled before every push.
Accomplishments that we're proud of
The interface. The design follows the subject: a dark, deep-water background where the only bright color marks results from the model. Results are ordered as the call, then the evidence, then the limitations, and the layout works on phones as well as laptops.
Generalization to an unseen family. On a random split, ESM-2 and BLAST perform about the same (AUC 0.990 vs. 0.981). When we hold out an entire protein family (LEA) during training, the gap opens: BLAST scores an AUC of 0.739, while ESM-2 scores 0.818. The model recognizes protective proteins from a family it never saw, where sequence alignment does worse. We also found that the CNN's filters had learned the dehydrin K-segment (EKKGIMDKIKEKLPG), a known motif that biologists identified by hand.
Fast explanations. The Gemini integration turns the model's feature contributions into a readable explanation quickly enough that it arrives with the score. If Gemini is unavailable, an offline fallback still explains the result.
Catching our own error. We'd rather report a lower number we can defend than a higher one we can't.
What we learned
Biochemistry vocabulary. We had to learn terms like intrinsically disordered, late embryogenesis abundant, anhydrobiosis and K-segment, and what they mean in practice. That included learning that "disordered" in one database doesn't mean the same thing in another.
Hosting on Vultr. We took the app from a laptop to a public server: pointing a domain at it, serving it over HTTPS with Caddy, running it as a restricted background service, and keeping the trained model and secrets out of the repository.
Adding authentication without weakening security. We integrated Auth0 for Google and approved .edu sign-in and learned where the details matter:
- we never handle or store passwords; Auth0 does
- the backend verifies every token's signature, issuer, audience and expiry, and makes access decisions on the server
- the app's database account can read and add records but can't delete them or change tables, and secrets stay in a restricted server file
Testing results that look too good. The shuffled-label and length-matched checks told us more than the headline accuracy did.
Choosing a hard baseline. Matching BLAST on a random split doesn't prove much. Holding out a whole family is a better test.
What's next for AnHydra
A research partner program. The model is limited by its training data. We want to let authorized research groups and universities submit sequences with lab results, including proteins that didn't protect. The sign-in system already supports approved institutional accounts, so it could serve as the entry point:
- Approved university and lab accounts sign in.
- They submit sequences along with their experimental results.
- We check each submission for quality, duplicates and source before it enters the dataset.
- New data improves the next model version, and partners can see what their data changed.
Over time, lab results would become the ground truth the model is measured against.
We also plan to:
- use stricter homology splits and taxonomic controls
- calibrate the scores so they can be read as probabilities
- support bulk screening, where a lab uploads a whole proteome and gets a ranked shortlist
Built at SwampHacks XII by Abdul Sidani, Benjamin Berrizbeitia, Gayathri Gunda and Vitor Ribeiro.
Built With
- auth0
- blast
- caddy
- cd-hit
- disprot
- esm-2
- fastapi
- gemini
- github-actions
- godaddy-registry
- hugging-face-transformers
- numpy
- pandas
- postgresql
- python
- pytorch
- react
- scikit-learn
- sqlalchemy
- typescript
- uniprot
- uvicorn
- vite
- vultr
Log in or sign up for Devpost to join the conversation.