Phenotype node genes grid returns NaN in JSON (invalid) when a gene matches HPO but not MONDO or vice versa - pandas 3 iterrows re-infers None to NaN
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
Research direction
Read snpdb/views/datatable_dataframe.py and inspect DataFrameTableView._rows(); the issue identifies iterrows() as the source of the NaN values under pandas 3. First check how rows are serialized, then add a regression test that serializes a frame with a missing cell and verifies strict JSON parsing with json.loads and parse_constant raising. Done when missing cells remain valid JSON nulls in the response.
Written by the indexing model from the issue text.
Description
🤖 Written by Claude
Reported from testing; root cause reproduced on a developer box.
Problem
The Phenotype node (and anything else served by DataFrameTableView) returns invalid JSON when the DataFrame has holes - a gene matched by an HPO term but not a MONDO term, or vice versa. The response contains bare NaN tokens, which JSON.parse rejects, so the node's genes grid fails with a JS error:
{"c0": "ELP4", "c1": "HP:0000526 Aniridia", "c2": NaN}, {"c0": "FOXC1", "c1": NaN, "c2": "MONDO:0019172 aniridia"}
Seen on analysis/<id>/node/ontology/genes/datatable/<node_id>/<version>/ for a Phenotype node reading its terms from a Sample node's patient, but any ontology genes grid with mixed HPO/OMIM/MONDO coverage will do it.
Cause
DataFrameTableView._dataframe() runs df_nan_to_none() (library/pandas_utils.py), which does work - the cells are None afterwards. But _rows() then walks the frame with df.iterrows(), and under pandas 3 each row Series is re-inferred as the new str dtype, which has no None: the missing values come back as NaN. itertuples() and to_dict(orient="records") both keep None, so the fix is to iterate one of those (or to_dict) in _rows() instead of iterrows(), in snpdb/views/datatable_dataframe.py.
Minimal reproduction:
df = pd.DataFrame.from_dict({'ELP4': {'HPO': 'x'}, 'FOXC1': {'MONDO': 'y'}}, orient='index')
a = df.astype(object).where(pd.notna(df), None)
a.iloc[0, 1] # None
next(a.iterrows())[1]['MONDO'] # nan <- str-dtype row Series
next(a.itertuples())[2] # None
Also worth a test on DataFrameTableView that serialises a frame with a missing cell and asserts the response parses as strict JSON (json.loads with parse_constant raising).
- Dominant language
- Python
- Stars
- 31
- Forks
- 4
- Avg merge
- 7h 20m
- Merged PRs (30d)
- 347
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from SACGF/variantgrid
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
SACGF/variantgrid#2737 · 1 comment ·
Maintainers usually reply within 1 day
-
Analysis bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
SACGF/variantgrid#2713 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
SACGF/variantgrid#2672 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
SACGF/variantgrid#2647 ·
Maintainers usually reply within 1 day
-
Remove unused DiscordanceLevel count properties from AlleleOverlapsPossibly taken A pull request linked to this issue is open or already merged. OpenRefactoring
Difficulty 1/5 Under an hour Newbie friendliness 90/100
SACGF/variantgrid#2424 ·
Maintainers usually reply within 1 day
All issues in SACGF/variantgrid
Similar issues
-
area:models enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
RedisStorage writes can persist a key without its sliding TTLPossibly taken @lianbie claimed this today. Opentriage/confirmed
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
agentscope-ai/agentscope#3878 · 1 comment ·
Maintainers usually reply within 2 days
-
core
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
vectorize-io/hindsight#6458 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 1-3 hours Newbie friendliness 82/100