Reference-table-based visual acuity conversion for ophthalmic research data harmonization.
Project description
Visual Acuity Conversion Toolkit
Version: 0.9.1
Status: pre-release / manuscript submission version
License: MIT License
A lightweight Python module for harmonizing visual acuity values across commonly used ophthalmic notation systems, including decimal acuity, Snellen notation, logMAR, approximate ETDRS letters, WHO vision impairment categories, and selected low-vision descriptors.
The toolkit was developed to support reproducible ophthalmic research, retrospective dataset cleaning, registry preprocessing, and transparent reporting of visual acuity conversion assumptions.
Purpose
Visual acuity is frequently documented in heterogeneous formats across clinical records, registries, retrospective datasets, and research studies. Common formats include decimal visual acuity, Snellen notation, logMAR, ETDRS letters, and low-vision descriptors such as counting fingers, hand movements, light perception, and no light perception.
These formats are related but not fully interchangeable. This package provides a transparent reference-table-based approach for harmonizing routinely documented visual acuity values while keeping conversion assumptions explicit and reproducible.
The package is intended for ophthalmic research, dataset cleaning, registry preprocessing, and transparent reporting of visual acuity conversion assumptions. It is not intended for clinical visual acuity measurement.
Installation
Install from PyPI:
pip install visual-acuity-conversion
Then import the module in Python:
from visual_acuity_conversion import convert_visual_acuity, get_va_chart
Dependencies
The package requires:
numpy
pandas
These dependencies are installed automatically when installing the package from PyPI.
Quick start
import pandas as pd
from visual_acuity_conversion import convert_visual_acuity
values = pd.Series(["6/6", "6/12", "6/60", "counting fingers"])
converted = convert_visual_acuity(
values,
input_format="Snellen_6m",
mode="exact"
)
print(converted)
Example output columns:
Decimal VA
logMAR
Snellen 6 m
Snellen 20 ft
Approx ETDRS letters
WHO class
Main functions
convert_visual_acuity()
convert_visual_acuity(series, input_format, mode="exact", return_columns=None)
Converts a pandas.Series of visual acuity values using the embedded reference conversion table.
Parameters
| Parameter | Description |
|---|---|
series |
A pandas.Series containing visual acuity values. |
input_format |
Input format of the visual acuity values. |
mode |
Conversion mode. Default is "exact". |
return_columns |
Optional subset of output columns to return. |
Supported input formats
Accepted values for input_format are:
| Input format | Description | Example values |
|---|---|---|
Decimal |
Decimal visual acuity | 1.0, 0.5, 0.32, 0,32 |
logMAR |
logMAR visual acuity | 0.0, 0.3, 1.0 |
Snellen_6m |
Snellen notation at 6 m | 6/6, 6/12, 3/60 |
Snellen_20ft |
Snellen notation at 20 ft | 20/20, 20/40, 20/200 |
ETDRS_letters |
Approximate ETDRS letters | 85, 70, 35 |
Off_chart |
Low-vision descriptors | counting fingers, hand movements, light perception, no light perception |
Output columns
By default, the package returns the following columns:
| Output column | Description |
|---|---|
Decimal VA |
Decimal visual acuity. |
logMAR |
logMAR visual acuity. |
Snellen 6 m |
Snellen notation at 6 m. |
Snellen 20 ft |
Snellen notation at 20 ft. |
Approx ETDRS letters |
Approximate ETDRS letter score. |
WHO class |
WHO visual impairment category. |
You can request a subset of columns:
converted = convert_visual_acuity(
values,
input_format="Snellen_6m",
return_columns=["Decimal VA", "logMAR", "WHO class"]
)
Inspecting the reference table
The embedded conversion table can be inspected directly:
from visual_acuity_conversion import get_va_chart
chart = get_va_chart()
print(chart.head())
This makes the conversion assumptions transparent and allows users to inspect the reference values used internally by the package.
Exact and nearest-neighbour conversion
Exact mode
Exact mode is the recommended default. It converts values only if they match an entry in the embedded reference table.
converted = convert_visual_acuity(
values,
input_format="Decimal",
mode="exact"
)
If no exact match is found, the output for that value is returned as missing.
Nearest-neighbour mode
Nearest-neighbour mode maps an input value to the closest predefined table entry.
converted = convert_visual_acuity(
values,
input_format="Decimal",
mode="near"
)
The aliases "close" and "closest" are also accepted.
Nearest-neighbour mode does not calculate a new continuous visual acuity value. It only selects the closest existing row from the embedded conversion table. This mode should be used cautiously and reported explicitly in analyses, reports, and manuscripts.
Low-vision descriptors
The toolkit includes approximate mappings for selected off-chart descriptors:
| Descriptor | Accepted aliases |
|---|---|
| Counting fingers | counting fingers, CF |
| Hand movements | hand movements, hand movement, hand motion, HM |
| Light perception | light perception, LP, follows light |
| No light perception | no light perception, NLP, nulla lux |
These mappings should be interpreted with caution because low-vision descriptors are not equivalent to standardized chart-based visual acuity measurements. Ambiguous or clinically important values should be reviewed manually.
Examples
Decimal visual acuity
import pandas as pd
from visual_acuity_conversion import convert_visual_acuity
values = pd.Series([1.0, 0.5, 0.1])
converted = convert_visual_acuity(
values,
input_format="Decimal"
)
print(converted)
logMAR visual acuity
values = pd.Series([0.0, 0.3, 1.0])
converted = convert_visual_acuity(
values,
input_format="logMAR"
)
print(converted)
Snellen visual acuity
values = pd.Series(["6/6", "6/12", "6/60"])
converted = convert_visual_acuity(
values,
input_format="Snellen_6m"
)
print(converted)
Off-chart descriptors
values = pd.Series(["counting fingers", "hand movements", "light perception", "no light perception"])
converted = convert_visual_acuity(
values,
input_format="Off_chart"
)
print(converted)
Recommended reporting in manuscripts
Suggested wording:
Visual acuity values were harmonized using the Visual Acuity Conversion Toolkit, version 0.9.1. Conversion was performed using exact lookup against the embedded reference table. Low-vision descriptors were mapped using predefined approximate values and interpreted cautiously.
If nearest-neighbour mode was used, this should be stated explicitly:
For values without an exact table match, nearest-neighbour lookup was used to map the input value to the closest predefined entry in the embedded conversion table. This approach did not interpolate new visual acuity values.
Limitations
This package is intended for transparent research data harmonization, not for clinical visual acuity measurement.
Important limitations:
- Snellen, decimal, logMAR, and ETDRS values are related but not fully interchangeable.
- Approximate ETDRS letters should not be interpreted as equivalent to standardized ETDRS chart testing.
- Low-vision descriptors do not have universally accepted numeric equivalents.
- Nearest-neighbour mode may introduce threshold-related misclassification.
- The package does not account for testing distance deviations, refraction status, pinhole testing, monocular versus binocular testing, or best-corrected versus presenting acuity.
- The package does not distinguish between monocular and binocular recordings.
- The current implementation does not automatically infer all input formats in a fully mixed-format column.
Users should retain original visual acuity values where possible and report conversion assumptions transparently.
Citation
This toolkit is currently released as a pre-publication software package. Until a journal article or archived DOI is available, please cite the PyPI package or software repository directly:
Poschkamp B, Jonas RA, Grün M, Kim H, Stahl A, Keane PA.
Visual Acuity Conversion Toolkit. Version 0.9.1.
Python Package Index: visual-acuity-conversion.
Accessed: [insert access date].
License
MIT License.
Copyright (c) 2026 Broder Poschkamp
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files to deal in the software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, subject to the conditions of the MIT License.
Disclaimer
This toolkit is provided for research and data-harmonization purposes. It is not a medical device and should not be used as a substitute for clinical visual acuity testing, clinical judgment, or standardized trial measurement protocols.
Low-vision descriptor mappings and approximate ETDRS conversions should be interpreted cautiously and reported transparently.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file visual_acuity_conversion-0.9.1.tar.gz.
File metadata
- Download URL: visual_acuity_conversion-0.9.1.tar.gz
- Upload date:
- Size: 10.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fe449c5ce5d0035d2c9196dff7a9011aab8e16cf4439f111a68bb4c254ee284
|
|
| MD5 |
1d96500a03fe269b8f0ffeae3269ec94
|
|
| BLAKE2b-256 |
88c72ed23d4c0f86cdbae964e61ca0b33794e0568f58307c4fc0bd315f08e185
|
File details
Details for the file visual_acuity_conversion-0.9.1-py3-none-any.whl.
File metadata
- Download URL: visual_acuity_conversion-0.9.1-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd93718b5fda99021b013149e5b769b6d22f6e463db060369152261f9189b06a
|
|
| MD5 |
9c2f53b532681f6b012d592ae187885a
|
|
| BLAKE2b-256 |
a173d35ddc8b5714a6992d88cc184b0f1007cd9dee461a0d05b3daf6c05ea273
|