<picture align="center">
<source media="(prefers-color-scheme: dark)" secset="https://js2iiu.com/wp-content/uploads/2024/12/adiftools_logo.png">
<img alt="adiftools Logo" src="https://js2iiu.com/wp-content/uploads/2024/12/adiftools_logo.png" width=500>
</picture>
----------------------
# adiftools: adif file utility tools for all amateur radio stations
| Item | Status |
| :---: | --- |
| Testing |     |
| Package |  |
| Meta | [](LICENSE)  |
| Stats |   |
## What is it?
**adiftools** is a Python package that provides utilities for ADIF data which is used for the QSO logging file format.
This tool offers the capability to load all QSO data from an ADIF file into a Pandas DataFrame. Additionally, it provides functionalities for graphing the loaded data, along with utility functions for Grid Locator-related latitude and longitude conversion and distance measurement.
## Main Features
- **ADIF file parser**: read ADIF file and convert to Pandas DataFrame
- Call signature:
```python
ADIFParser.read_adi(file_path, enable_timestamp=False)
```
- Parameter:
- `file_path`: str or path-like or binary file-like
- A path, or a Python file-like object of ADIF file to read
- Returns:
- `pd.DataFrame`
- The created pandas.DataFrame instance includes QSO data from ADIF file
- Other Parameter:
- `enable_timestamp`: bool, default: `False`
- If True, add row named ['timestamp'] to DataFrame which is generated from ADIF file. The row ['timestamp'] is `datetime64[ns]` type and based on rows `'QSO_DATE'` and `'TIME_ON'`.
- **Save ADIF data as adi file**
- Saves the loaded ADIF data as an adi file conforming to the ADIF standard. adiftools adds a new header to the beginning of the adi file.
- Fields with no data are filled with `nan`.
- The header will contain information on the following two fields, CREATED_TIMESTAMP, and PROGRAMID.
- Call signature:
```python
ADIFParser.to_adi(file_path)
```
- Parameter:
- `file_path`: str or path-like or binary file-like
- A path, or a Python file-like object of adi file to save
- Returns:
- `None`
- **Save ADIF data as pickle file**: Save the DataFrame with the ADIF loaded to a pickle file.
- Loading an ADIF file into a DataFrame can be quite time consuming.
- It is especially long if there are many QSOsin the ADIF file, and it is very cumbersome to read the data every time.
- It is recommended to serialize the ADIF data once loaded and save it in a pickle format, which is expected to be 50 times faster than loading a raw ADIF file.
- Call signature:
```python
ADIFParser.to_pickle(file_path)
```
- Parameter:
- `file_path`: str or path-like or binary file-like
- A path, or a Python file-like object of pickle file to save
- Returns:
- `None`
- **Load Pickle data**
- Provides a way to read ADIF data once it has been loaded by ADIFParser and saved in a pickle file.
- The read_pickle method does not check whether the QSO data is saved in the read pickle file.
- Call signature:
```python
ADIFParser.read_pickle(file_path)
```
- Parameter:
- `file_path`: str or path-like or binary file-like
- A path, or a Python file-like object of pickle file to read
- Returns:
- `pd.DataFrame`
- The created pandas.DataFrame instance includes QSO data from ADIF file
- **Save ADIF data as excel file**: Save the DataFrame with the ADIF loaded to an excel file.
- Call signature:
```python
ADIFParser.to_excel(file_path)
```
- Parameter:
- `file_path`: str or path-like or binary file-like
- A path, or a Python file-like object of excel file to save
- Returns:
- `None`
- **Generate Callsign file**
- Outputs call sign data without duplicates from data read from an ADIF file as a text file. The text file will contain one callsign per line.
- If the ADIF file has not been read, i.e., `read_adi()` has not been performed, it returns the error `AdifParserError`.
- Call signature:
```python
ADIFParser.call_to_txt(file_path)
```
- Parameter:
- `file_path`: str or path-like or binary file-like
- A path of output txt file
- Returns:
- `None`
- **ADIF data monthly plot**: Generate monthly QSO plot
- Call signature:
```python
ADIFParser.plot_monthly(file_path)
```
Generates a bar plot of monthly QSOs and saves a PNG or JPG file.
- Parameters:
- `file_path`: str or path-like or binary file-like
- A path or a Python file-like object of the plot's PNG or JPG file.
- Returns:
- `None`
<img src="https://js2iiu.com/wp-content/uploads/2024/12/monthly_qso_aa.png" width=600>
- **Monthly Band QSO Stacked Bar Plot**: Generate stacked bar plot of monthly QSO counts by band
- Call signature:
```python
ADIFParser.plot_monthly_band(file_path)
```
Generates a stacked bar plot of monthly QSO counts by band and saves a PNG or JPG file.
Each band is assigned a unique color for clarity. The color table for each BAND is defined inside the function, and if a BAND is not listed, a unique color is automatically assigned from a colormap to avoid duplication.
- Parameters:
- `file_path`: str or path-like or binary file-like
- A path or a Python file-like object of the plot's PNG or JPG file.
- Returns:
- `None`
<!-- Add a sample image here if available -->
- **Band percentage plot**: Generate pie plot to show QSO-Band percentage
- Call signature:
```python
ADIFParser.plot_band_percentage(file_path)
```
Generates a pie plot of QSO-band counts and saves a PNG or JPG file.
- Parameters:
- `file_path`: str or path-like or binary file-like
- A path or a Python file-like object of the plot's PNG or JPG file.
- Returns:
- `None`
<img src="https://js2iiu.com/wp-content/uploads/2025/01/percentage_band.png" width=500>
- **Grid Locator utilities**
- Calculate geographic coordination from GL
- Call signature:
```python
adiftools.gl2latlon(gridlocator)
```
- Parameter:
- `gridlocator`: str of grid locator. 4 or 6 digits, regardless of upper or lower case.
- Returns:
- `(latitude, longitude)`: tuple of latitude and longitude in decimal degree unit (DD/DEG format).
- Calculate grid locators from latitude and longitude
- Call signature
```python
adiftools.latlon2gl(latitude, longitude, fourdigit=False)
```
- Parameters:
- `latitude` in decimal degree unit
- `longitude` in decimal degree unit
- `fourdigit` if True, returns 4-digit grid square
- Reference
- [Edmund T. Tyson, N5JTY, Conversion Between Geodetic and Grid Locator Systems, QST January 1989, pp. 29-30, 43](http://radio-amador.net/pipermail/cluster/attachments/20120105/3611b154/conversion_geodetic_grid.pdf)
- Calculate distance from two places' latitude and longitude
- Call signature
```python
adiftools.get_dist(lat1, lon1, lat2, lon2)
```
- Parameters:
- `lat1` – latitude of the first point in degrees
- `lon1` – longitude of the first point in degrees
- `lat2` – latitude of the second point in degrees
- `lon2` – longitude of the second point in degrees
- Returns:
- the distance from the first point to the second in meters
- Reference
- [GeographicLib API — geographiclib 2.0 documentation](https://geographiclib.sourceforge.io/Python/doc/code.html#)
- **Call Sign Utility**
- Check JA call sign
- Call signature
```python
adiftools.is_ja(call_sign)
```
- Parameter:
- `call_sign` call sign in string
- Returns:
- `True`: JA call, `False`: other
- Check Area
- Call signature
```python
adiftools.get_area(call_sign)
```
- Parameter:
- `call_sign` call sign in string
- Returns:
- `number`: area number, `None`: n/a
Note: `adiftools` is not support ADX file format at this moment.
## Install
adiftools has been tested against Python 3.11, 3.12, and 3.13. It may work with Python 3 prior to 3.10, but we recommend using 3.11 or higher versions.
It is recommended to create a virtual environment and install adiftools inside the virtual environment.
Binary installers for the latest released version is available via PyPI: [adiftools · PyPI](https://pypi.org/project/adiftools/).
```sh
pip install adiftools
```
If you are using an older version of adiftools, please use the following command to update it to the latest version.
```sh
pip install -U adiftools
```
Unfortunately, if you no longer need adiftools, you can uninstall it with the following command.
```sh
pip uninstall adiftools
```
### Testing version
**We have decided not to update adiftools on the TestPyPI site anymore.**
For detail, please see TestPyPI website: [adiftools · TestPyPI](https://test.pypi.org/project/adiftools/0.0.5/)
```sh
pip install -i https://test.pypi.org/simple/ adiftools==0.0.5
```
## Getting Started
The first step in utilizing adiftools is to load an ADIF file; files that follow the ADIF standard can be loaded. After loading an adif file, you can perform graphing and other operations. Please refer to this page for ADIF standard. [The Independent ADIF Site](https://www.adif.org/)
Example:
```python
import adiftools.adiftools as adiftools
adi = adiftools.ADIFParser()
df_adi = adi.read_adi('sample.adi') # Use your own adi file
print(df)
```
## Dependencies
- [Pandas](https://pandas.pydata.org)
- [numpy](https://numpy.org/doc/stable/index.html)
- [matplotlib](https://matplotlib.org)
- [GeographicLib API](https://geographiclib.sourceforge.io/Python/doc/code.html)
## Licence
[MIT](LICENSE)
## 日本語での情報提供
Information in Japanese is available on the following blogs. Information updates are prioritised on Github, and information updates on the following blogs are slightly delayed.
- [adiftools | アマチュア無線局JS2IIU](https://js2iiu.com/adiftools/)
TU de JS2IIU 73
Raw data
{
"_id": null,
"home_page": "https://github.com/JS2IIU-MH/adiftools-dev",
"name": "adiftools",
"maintainer": "JS2IIU",
"docs_url": null,
"requires_python": null,
"maintainer_email": "info@js2iiu.com",
"keywords": "adif",
"author": "JS2IIU",
"author_email": "info@js2iiu.com",
"download_url": "https://files.pythonhosted.org/packages/c0/da/c2bd074305355a902fcd04455e0674916611a6c1f5e5e884c556d18f7fb7/adiftools-0.1.9.tar.gz",
"platform": null,
"description": "<picture align=\"center\">\n <source media=\"(prefers-color-scheme: dark)\" secset=\"https://js2iiu.com/wp-content/uploads/2024/12/adiftools_logo.png\">\n <img alt=\"adiftools Logo\" src=\"https://js2iiu.com/wp-content/uploads/2024/12/adiftools_logo.png\" width=500>\n</picture>\n\n----------------------\n\n# adiftools: adif file utility tools for all amateur radio stations\n\n| Item | Status |\n| :---: | --- |\n| Testing |     |\n| Package |  |\n| Meta | [](LICENSE)  |\n| Stats |   |\n\n## What is it?\n\n**adiftools** is a Python package that provides utilities for ADIF data which is used for the QSO logging file format.\n\nThis tool offers the capability to load all QSO data from an ADIF file into a Pandas DataFrame. Additionally, it provides functionalities for graphing the loaded data, along with utility functions for Grid Locator-related latitude and longitude conversion and distance measurement.\n\n## Main Features\n\n- **ADIF file parser**: read ADIF file and convert to Pandas DataFrame\n - Call signature:\n ```python\n ADIFParser.read_adi(file_path, enable_timestamp=False)\n ```\n - Parameter:\n - `file_path`: str or path-like or binary file-like\n - A path, or a Python file-like object of ADIF file to read\n - Returns:\n - `pd.DataFrame`\n - The created pandas.DataFrame instance includes QSO data from ADIF file \n \n - Other Parameter:\n - `enable_timestamp`: bool, default: `False`\n - If True, add row named ['timestamp'] to DataFrame which is generated from ADIF file. The row ['timestamp'] is `datetime64[ns]` type and based on rows `'QSO_DATE'` and `'TIME_ON'`.\n\n- **Save ADIF data as adi file**\n - Saves the loaded ADIF data as an adi file conforming to the ADIF standard. adiftools adds a new header to the beginning of the adi file.\n - Fields with no data are filled with `nan`.\n - The header will contain information on the following two fields, CREATED_TIMESTAMP, and PROGRAMID.\n - Call signature:\n ```python\n ADIFParser.to_adi(file_path)\n ```\n - Parameter:\n - `file_path`: str or path-like or binary file-like\n - A path, or a Python file-like object of adi file to save\n - Returns:\n - `None`\n\n- **Save ADIF data as pickle file**: Save the DataFrame with the ADIF loaded to a pickle file.\n - Loading an ADIF file into a DataFrame can be quite time consuming.\n - It is especially long if there are many QSOsin the ADIF file, and it is very cumbersome to read the data every time.\n - It is recommended to serialize the ADIF data once loaded and save it in a pickle format, which is expected to be 50 times faster than loading a raw ADIF file.\n - Call signature:\n ```python\n ADIFParser.to_pickle(file_path)\n ```\n - Parameter:\n - `file_path`: str or path-like or binary file-like\n - A path, or a Python file-like object of pickle file to save\n - Returns:\n - `None`\n\n- **Load Pickle data**\n - Provides a way to read ADIF data once it has been loaded by ADIFParser and saved in a pickle file.\n - The read_pickle method does not check whether the QSO data is saved in the read pickle file.\n - Call signature:\n ```python\n ADIFParser.read_pickle(file_path)\n ```\n - Parameter:\n - `file_path`: str or path-like or binary file-like\n - A path, or a Python file-like object of pickle file to read\n - Returns:\n - `pd.DataFrame`\n - The created pandas.DataFrame instance includes QSO data from ADIF file \n\n- **Save ADIF data as excel file**: Save the DataFrame with the ADIF loaded to an excel file.\n - Call signature:\n ```python\n ADIFParser.to_excel(file_path)\n ```\n - Parameter:\n - `file_path`: str or path-like or binary file-like\n - A path, or a Python file-like object of excel file to save\n - Returns:\n - `None`\n\n- **Generate Callsign file**\n - Outputs call sign data without duplicates from data read from an ADIF file as a text file. The text file will contain one callsign per line.\n - If the ADIF file has not been read, i.e., `read_adi()` has not been performed, it returns the error `AdifParserError`.\n - Call signature:\n ```python\n ADIFParser.call_to_txt(file_path)\n ```\n - Parameter:\n - `file_path`: str or path-like or binary file-like\n - A path of output txt file\n - Returns:\n - `None`\n\n\n\n- **ADIF data monthly plot**: Generate monthly QSO plot\n - Call signature:\n ```python\n ADIFParser.plot_monthly(file_path)\n ```\n Generates a bar plot of monthly QSOs and saves a PNG or JPG file.\n - Parameters:\n - `file_path`: str or path-like or binary file-like\n - A path or a Python file-like object of the plot's PNG or JPG file.\n - Returns:\n - `None`\n \n <img src=\"https://js2iiu.com/wp-content/uploads/2024/12/monthly_qso_aa.png\" width=600>\n\n\n\n- **Monthly Band QSO Stacked Bar Plot**: Generate stacked bar plot of monthly QSO counts by band\n - Call signature:\n ```python\n ADIFParser.plot_monthly_band(file_path)\n ```\n Generates a stacked bar plot of monthly QSO counts by band and saves a PNG or JPG file.\n Each band is assigned a unique color for clarity. The color table for each BAND is defined inside the function, and if a BAND is not listed, a unique color is automatically assigned from a colormap to avoid duplication.\n - Parameters:\n - `file_path`: str or path-like or binary file-like\n - A path or a Python file-like object of the plot's PNG or JPG file.\n - Returns:\n - `None`\n \n <!-- Add a sample image here if available -->\n\n\n- **Band percentage plot**: Generate pie plot to show QSO-Band percentage\n - Call signature:\n ```python\n ADIFParser.plot_band_percentage(file_path)\n ```\n Generates a pie plot of QSO-band counts and saves a PNG or JPG file.\n - Parameters:\n - `file_path`: str or path-like or binary file-like\n - A path or a Python file-like object of the plot's PNG or JPG file.\n - Returns:\n - `None`\n\n <img src=\"https://js2iiu.com/wp-content/uploads/2025/01/percentage_band.png\" width=500>\n\n\n- **Grid Locator utilities**\n - Calculate geographic coordination from GL\n - Call signature:\n ```python\n adiftools.gl2latlon(gridlocator)\n ```\n - Parameter:\n - `gridlocator`: str of grid locator. 4 or 6 digits, regardless of upper or lower case.\n - Returns:\n - `(latitude, longitude)`: tuple of latitude and longitude in decimal degree unit (DD/DEG format).\n\n - Calculate grid locators from latitude and longitude\n - Call signature\n ```python\n adiftools.latlon2gl(latitude, longitude, fourdigit=False)\n ```\n - Parameters:\n - `latitude` in decimal degree unit\n - `longitude` in decimal degree unit\n - `fourdigit` if True, returns 4-digit grid square\n\n - Reference\n - [Edmund T. Tyson, N5JTY, Conversion Between Geodetic and Grid Locator Systems, QST January 1989, pp. 29-30, 43](http://radio-amador.net/pipermail/cluster/attachments/20120105/3611b154/conversion_geodetic_grid.pdf)\n\n - Calculate distance from two places' latitude and longitude\n - Call signature\n ```python\n adiftools.get_dist(lat1, lon1, lat2, lon2)\n ```\n - Parameters:\n - `lat1` \u2013 latitude of the first point in degrees\n - `lon1` \u2013 longitude of the first point in degrees\n - `lat2` \u2013 latitude of the second point in degrees\n - `lon2` \u2013 longitude of the second point in degrees\n - Returns:\n - the distance from the first point to the second in meters\n - Reference\n - [GeographicLib API \u2014 geographiclib 2.0 documentation](https://geographiclib.sourceforge.io/Python/doc/code.html#)\n\n- **Call Sign Utility**\n - Check JA call sign\n - Call signature\n ```python\n adiftools.is_ja(call_sign)\n ```\n - Parameter:\n - `call_sign` call sign in string\n - Returns:\n - `True`: JA call, `False`: other\n - Check Area\n - Call signature\n ```python\n adiftools.get_area(call_sign)\n ```\n - Parameter:\n - `call_sign` call sign in string\n - Returns:\n - `number`: area number, `None`: n/a \n\nNote: `adiftools` is not support ADX file format at this moment.\n\n## Install\n\nadiftools has been tested against Python 3.11, 3.12, and 3.13. It may work with Python 3 prior to 3.10, but we recommend using 3.11 or higher versions.\n\nIt is recommended to create a virtual environment and install adiftools inside the virtual environment.\n\nBinary installers for the latest released version is available via PyPI: [adiftools \u00b7 PyPI](https://pypi.org/project/adiftools/).\n\n```sh\npip install adiftools\n```\n\nIf you are using an older version of adiftools, please use the following command to update it to the latest version.\n```sh\npip install -U adiftools\n```\n\nUnfortunately, if you no longer need adiftools, you can uninstall it with the following command.\n```sh\npip uninstall adiftools\n```\n\n### Testing version\n**We have decided not to update adiftools on the TestPyPI site anymore.**\n\nFor detail, please see TestPyPI website: [adiftools \u00b7 TestPyPI](https://test.pypi.org/project/adiftools/0.0.5/)\n\n```sh\npip install -i https://test.pypi.org/simple/ adiftools==0.0.5\n```\n\n## Getting Started\nThe first step in utilizing adiftools is to load an ADIF file; files that follow the ADIF standard can be loaded. After loading an adif file, you can perform graphing and other operations. Please refer to this page for ADIF standard. [The Independent ADIF Site](https://www.adif.org/)\n\nExample:\n```python\nimport adiftools.adiftools as adiftools\n\nadi = adiftools.ADIFParser()\n\ndf_adi = adi.read_adi('sample.adi') # Use your own adi file\nprint(df)\n```\n\n## Dependencies\n- [Pandas](https://pandas.pydata.org)\n- [numpy](https://numpy.org/doc/stable/index.html)\n- [matplotlib](https://matplotlib.org)\n- [GeographicLib API](https://geographiclib.sourceforge.io/Python/doc/code.html)\n\n## Licence\n[MIT](LICENSE)\n\n## \u65e5\u672c\u8a9e\u3067\u306e\u60c5\u5831\u63d0\u4f9b\nInformation in Japanese is available on the following blogs. Information updates are prioritised on Github, and information updates on the following blogs are slightly delayed.\n- [adiftools | \u30a2\u30de\u30c1\u30e5\u30a2\u7121\u7dda\u5c40JS2IIU](https://js2iiu.com/adiftools/)\n\nTU de JS2IIU 73\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "ADIF file utilities",
"version": "0.1.9",
"project_urls": {
"Download": "https://github.com/JS2IIU-MH/adiftools-dev",
"Homepage": "https://github.com/JS2IIU-MH/adiftools-dev"
},
"split_keywords": [
"adif"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "cc90fd6e7600fbf076c271561dc7a71e0b4f36f80e8f63c1b4c9162afa7e2262",
"md5": "25bc0e23071f7e843d1965295a629709",
"sha256": "a2ad245298ab7615585242ea2b1d52c06131102a2bf0bb108e0742d00329696e"
},
"downloads": -1,
"filename": "adiftools-0.1.9-py3-none-any.whl",
"has_sig": false,
"md5_digest": "25bc0e23071f7e843d1965295a629709",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 13032,
"upload_time": "2025-08-11T11:38:57",
"upload_time_iso_8601": "2025-08-11T11:38:57.102286Z",
"url": "https://files.pythonhosted.org/packages/cc/90/fd6e7600fbf076c271561dc7a71e0b4f36f80e8f63c1b4c9162afa7e2262/adiftools-0.1.9-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c0dac2bd074305355a902fcd04455e0674916611a6c1f5e5e884c556d18f7fb7",
"md5": "87b6e5fe82f046b68d4567d191d91f5b",
"sha256": "39bf8d67bbd29eb7008d710d42bb8fa88601f6f1b10a46e24c34c09423e12651"
},
"downloads": -1,
"filename": "adiftools-0.1.9.tar.gz",
"has_sig": false,
"md5_digest": "87b6e5fe82f046b68d4567d191d91f5b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 17438,
"upload_time": "2025-08-11T11:38:58",
"upload_time_iso_8601": "2025-08-11T11:38:58.833876Z",
"url": "https://files.pythonhosted.org/packages/c0/da/c2bd074305355a902fcd04455e0674916611a6c1f5e5e884c556d18f7fb7/adiftools-0.1.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-11 11:38:58",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "JS2IIU-MH",
"github_project": "adiftools-dev",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "numpy",
"specs": []
},
{
"name": "pandas",
"specs": []
},
{
"name": "matplotlib",
"specs": []
},
{
"name": "python-dateutil",
"specs": []
},
{
"name": "pytz",
"specs": []
},
{
"name": "six",
"specs": []
},
{
"name": "tzdata",
"specs": []
},
{
"name": "geographiclib",
"specs": []
},
{
"name": "iniconfig",
"specs": []
},
{
"name": "pluggy",
"specs": []
}
],
"lcname": "adiftools"
}