Skip to content

[DCP - SigFigs] Preserve SigFigs through Dataflow. Stop converting to double/int - #723

Open
gmechali wants to merge 5 commits into
datacommonsorg:masterfrom
gmechali:sigfigDataFlow
Open

[DCP - SigFigs] Preserve SigFigs through Dataflow. Stop converting to double/int#723
gmechali wants to merge 5 commits into
datacommonsorg:masterfrom
gmechali:sigfigDataFlow

Conversation

@gmechali

@gmechali gmechali commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Refactors observation value handling across the Dataflow ingestion pipeline and Java utilities to use exact raw string representations, eliminating precision loss and significant figure degradation caused by floating-point conversions.

  • Protobuf (Mcf.proto): Reserved field 2 (number) in McfStatVarObsSeries.StatVarObs and streamlined observation value representation to optional string text = 3.
  • Graph Reader (GraphReader.java): Updated toObservation to deserialize Observation.value directly using obs.getText().
  • Graph Utils (GraphUtils.java): Populate McfStatVarObsSeries with raw string text; removed dead numeric-conversion helper methods.
  • Consistency Checker (StatChecker.java):
    • Store svObValues as String in ConcurrentMap to prevent float-rounding collisions on high-precision inputs.
    • Used atomic putIfAbsent in checkSvObsValueInconsistency to ensure thread-safety and avoid race conditions under concurrent execution.
  • Test Goldens (tool/): Updated report.json test expectations in datacommons-import-tool to reflect exact raw string messages.

Testing

  • Unit Tests: All Java unit tests passing across modules (util/, pipeline/util/, tool/).
  • Formatting: Verified 0 non-complying files with mvn fmt:check.
  • End-to-End Live Verification:
    • Deployed custom Dataflow Flex Template (ingestion-gabe-test.json).
    • Ingested samples/sigfig_test JSON-LD shards into live Spanner database (gmechali-latest-dc-db).
    • Ran read queries on Spanner Observation table and confirmed 100% of observations match exact raw input strings (12.50, 12.5000, 0.0000001230, 100000000000000001, -15.00).

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the ingestion pipeline to prefer raw string/text representations of observation values over double/float representations. This change preserves significant figures and avoids floating-point precision issues or scientific notation formatting. It updates GraphReader, GraphUtils, and StatChecker to use text fields, removes the unused nodeDoubleValue helper, and updates corresponding unit tests to verify significant figure preservation. There are no review comments, so I have no feedback to provide.

@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 2 minor

Alerts:
⚠ 2 issues (≤ 0 issues of at least minor severity)

Results:
2 new issues

Category Results
CodeStyle 2 minor

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@gmechali

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors observation value handling to use raw string representations instead of floating-point numbers, aiming to preserve significant figures and prevent precision loss. Key changes include removing the number field from McfStatVarObsSeries.StatVarObs in favor of text, and updating associated reader, utility, and checker classes. The review feedback highlights two critical issues: first, reserving the number field in the proto definition breaks backward compatibility with legacy serialized data, so keeping it as a deprecated optional field is recommended; second, a non-atomic check-and-act pattern in StatChecker introduces a race condition under concurrent execution, which should be resolved using putIfAbsent.

Comment thread util/src/main/proto/Mcf.proto
Comment thread util/src/main/java/org/datacommons/util/StatChecker.java Outdated
"lineNumber": "3"
},
"userMessage": "Found nodes with different values for the same StatVarObservation :: observationAbout: 'geoId/01', variableMeasured: 'Some_StatVar', observationDate: '2020-01-01', value1: 1.0, value2: 2.0",
"userMessage": "Found nodes with different values for the same StatVarObservation :: observationAbout: 'geoId/01', variableMeasured: 'Some_StatVar', observationDate: '2020-01-01', value1: 1, value2: 2",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi the reason we are now removing the "1.0" and instead showing "1" isnt' about a loss of sigfigs but actually preservation of sigfigs.

We used to convert the 1 to a float making it 1.0. Now we preserve the value.

"location": {
"file": "covid.mcf",
"lineNumber": "17"
"entries": [

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the only diffs here are the same as the other two report.jsons (preserving sigfigs). This is just a formatting diff

@gmechali

Copy link
Copy Markdown
Contributor Author

FYI - this fix works in conjunction with #724

@vish-cs Can you pls take a look at both of these PRs and ensure that we're okay from a base dc perspective as well? Im specifically interested in your opinion on the "batch job", our "ET" part. I m not super familiar with it and want to make sure that you're not expecting dataflow to process those as numbers. The current PR deprecates using numbers on the MCF Obs object.

Side note: we are likely to see some significant diffs in data as we begin to ingest more data with this version of dataflow. It should only ever be differences to the observation values to ensure the sigfigs are preserved. It should be simple to verify, but something we ll all need to keep an eye out for.

@clincoln8 clincoln8 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

string text = 3;
}
// Value of the observation in text format.
optional string text = 3;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: consider just naming this value
Totally understand if it's not worth a bunch of extra overhead though

if (this.svObValues.containsKey(fp) && !this.svObValues.get(fp).equals(val)) {
String val = McfUtil.getPropVal(node, Vocabulary.VALUE);
String existingVal = this.svObValues.putIfAbsent(fp, val);
if (existingVal != null && !existingVal.equals(val)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

acking that comparing raw strings here means duplicate observations with different precision formatting (like 12.5 vs 12.50) will now flag as an error.
This makes sense to enforce strict SigFig consistency and eliminates the old float truncation issues.

@rohitkumarbhagat

Copy link
Copy Markdown
Contributor

Thanks Gabe. Is there a doc/read where the severity of issue is discussed. There were discussions of saving numeric values in spanner for query time benefits (inline arithmetic operations). Would be better to evaluate before we make wider change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants