{"id":44026479,"url":"https://github.com/imker25/gpsa","last_synced_at":"2026-02-07T18:00:56.505Z","repository":{"id":41997969,"uuid":"233253105","full_name":"imker25/gpsa","owner":"imker25","description":"This is a simple command line tool that helps to extract data for statistical analysis out of track files like *.gpx","archived":false,"fork":false,"pushed_at":"2026-02-05T21:09:52.000Z","size":707,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-06T07:18:59.371Z","etag":null,"topics":["csv-export","gps","gpx-parser","json-export","statistics","tcx-parser"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imker25.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-01-11T15:29:59.000Z","updated_at":"2025-10-16T18:07:47.000Z","dependencies_parsed_at":"2024-12-21T17:43:46.516Z","dependency_job_id":"98765698-d0fe-43a9-9efb-eb9e773a29b4","html_url":"https://github.com/imker25/gpsa","commit_stats":null,"previous_names":[],"tags_count":84,"template":false,"template_full_name":null,"purl":"pkg:github/imker25/gpsa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imker25%2Fgpsa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imker25%2Fgpsa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imker25%2Fgpsa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imker25%2Fgpsa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imker25","download_url":"https://codeload.github.com/imker25/gpsa/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imker25%2Fgpsa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29202961,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T17:44:10.191Z","status":"ssl_error","status_checked_at":"2026-02-07T17:44:07.936Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csv-export","gps","gpx-parser","json-export","statistics","tcx-parser"],"created_at":"2026-02-07T18:00:35.290Z","updated_at":"2026-02-07T18:00:56.491Z","avatar_url":"https://github.com/imker25.png","language":"Go","readme":"# gpsa - A GPX Statistic extracting tool\n\nThis is a simple command line tool that helps to extract data for statistical analysis out of `*.gpx` and `*.tcx` files. You might want to use this program to extract data like `Distance`, `ElevationGain` or `AverageSpeed` from a bunch of `*.gpx` or `*.tcx` files and store this data in a *.csv or *.json file for further analysis.\n\n- [gpsa - A GPX Statistic extracting tool](#gpsa---a-gpx-statistic-extracting-tool)\n  - [User Documentation](#user-documentation)\n    - [Installation](#installation)\n    - [Usage](#usage)\n      - [Help Command](#help-command)\n      - [Examples](#examples)\n      - [Output Values explained](#output-values-explained)\n  - [Development](#development)\n    - [Build](#build)\n    - [Hints for VSCode Users](#hints-for-vscode-users)\n  - [Geo Math Internals](#geo-math-internals)\n  - [License](#license)\n\n## User Documentation\n\nSome documentation and examples about gpsa usage.\n\n### Installation\n\nDownload the latest release executable from [GitHub Release](https://github.com/imker25/gpsa/releases/latest) according to your operation system and copy the file to a empty folder.\n\n**On Linux**, open a command line and set the file executable:\n\n```sh\nchmod 770 ./gpsa\n\n# You may want to get the programs help\n./gpsa -help\n```\n\n**On Windows**, open the command window in this folder and execute the program (may with the -help flag):\n\n```batch\n.\\gpsa.exe -help\n```\n\n### Usage\n\nBelow you can find some kind of user manual for this program.\n\n#### Help Command\n\nYou might want to call ```-help``` to find out how to use the program.\n\n```txt\n~$ ./gpsa -help\n./bin/gpsa: Reads in GPS track files, and writes out basic statistic data found in the track as a report\nProgram Version: 2.3.6-4142b3b\n\nUsage: ./bin/gpsa [options] [files]\n  files\n        One or more track files of the following type: *.tcx, *.gpx, \nOptions:\n  -correction string\n    \tDefine how to correct the elevation data read in from the track. Possible values are [steps linear none ] (default \"steps\")\n  -depth string\n    \tDefine the way the program should analyse the files. Possible values are [segment file track ] (default \"track\")\n  -dont-panic\n    \tDecide if the program will exit with panic or with negative exit code in error cases. Possible values are [true false] (default true)\n  -help\n    \tPrint help message and exit\n  -license\n    \tPrint license information of the program and exit\n  -minimal-moving-speed float\n    \tThe minimal speed. Distances traveled with less speed are not counted. In [m/s] (default 0.3)\n  -maximum-start-time string\n        The maximum StartTime for a track to be added to the output. Formatted in \"YYYY-MMM-dd HH:mm:ss\", may without seconds or just a date\n  -minimum-start-time string\n        The minimum StartTime for a track to be added to the output. Formatted in \"YYYY-MMM-dd HH:mm:ss\", may without seconds or just a date      \n  -minimal-step-hight float\n    \tThe minimal step hight. Only in use when \"steps\"  elevation correction is used. In [m] (default 10)\n  -out-file string\n    \tDecide where to write the output. StdOut is used when not explicitly set. Supported file endings are: *.md *.json, *.csv, . The format will be set according the given ending.\n  -print-csv-header\n    \tPrint out a csv header line. Possible values are [true false] (default true)\n  -print-elevation-over-distance\n    \tTell if \"ElevationOverDistance.csv\" should be created for each track. The files will be locate in tmp dir.\n  -skip-error-exit\n    \tDon't exit the program on track file processing errors\n  -std-out-format string\n    \tThe output format when stdout is the used output. Ignored when out-file is given. Possible values are [JSON CSV  MD] (default \"CSV\")\n  -summary string\n    \tTell if you want to get a summary report. Possible values are [only additional none ] (default \"none\")\n  -suppress-duplicate-out-put\n    \tSuppress the output of duplicate lines. Duplicates are detected by timestamps. Output with non valid time data may still contains duplicates.\n  -time-format string\n    \tTell how the csv output formater should format times. Possible values are [\"Mon Jan _2 15:04:05 MST 2006\" \"Monday, 02-Jan-06 15:04:05 MST\" \"2006-01-02T15:04:05Z07:00\" ] (default \"Monday, 02-Jan-06 15:04:05 MST\")\n  -verbose\n    \tRun the program with verbose output\n  -version\n    \tPrint version of the program and exit\n\nIt is also possible to pipe track file names or track file content into\n\nExamples:\n./gpsa my/test/file.gpx\n./gpsa -verbose -out-file=gps-statistics.csv my/test/*.gpx\nfind ./testdata/valid-gpx -name \"*.gpx\" | ./bin/gpsa -summary=additional -out-file=./test.json\ncat  01.gpx 01.tcx 03.tcx 02.gpx | ./bin/gpsa -out-file=./test.json\n```\n\n#### Examples\n\nSimple call with one file:\n\n```sh\n~$  ./gpsa my/test/file.gpx\nName; StartTime; EndTime; TrackTime (xxhxxmxxs); Distance (km); HorizontalDistance (km); AltitudeRange (m); MinimumAltitude (m); MaximumAltitude (m); ElevationGain (m); ElevationLose (m); UpwardsDistance (km); DownwardsDistance (km); MovingTime (xxhxxmxxs); UpwardsTime (xxhxxmxxs); DownwardsTime (xxhxxmxxs); AverageSpeed (km/h); UpwardsSpeed (km/h); DownwardsSpeed (km/h);\nmy/test/file.gpx: 2020-01-29 09:28:06;2020-01-29T08:28:10Z; 2020-01-29T13:48:07Z; 5h19m53s; 94.75; 90.25; 1188.37; 821.61; 2009.98; 10659.34; -10884.50; 43.47; 51.00; 4h1m44s; 2h8m49s; 1h52m55s; 23.52; 20.25; 27.10; \n\n```\n\nSimple call with multiple files:\n\n```sh\n~$  ./gpsa my/test/01.gpx my/test/02.tcx my/test/03.gpx\nName; StartTime; EndTime; TrackTime (xxhxxmxxs); Distance (km); HorizontalDistance (km); AltitudeRange (m); MinimumAltitude (m); MaximumAltitude (m); ElevationGain (m); ElevationLose (m); UpwardsDistance (km); DownwardsDistance (km); MovingTime (xxhxxmxxs); UpwardsTime (xxhxxmxxs); DownwardsTime (xxhxxmxxs); AverageSpeed (km/h); UpwardsSpeed (km/h); DownwardsSpeed (km/h);\n03.gpx: Tulln - Wien; not valid; not valid; not valid; 37.64; 36.12; 48.00; 158.00; 206.00; 52.00; -26.00; 17.52; 14.06; not valid; not valid; not valid; not valid; not valid; not valid;\n02.gpx: 2019-08-18 11:07:40; 2019-08-18T09:11:01Z; 2019-08-18T15:47:34Z; 1h35m40s; 37.82; 37.23; 104.09; 347.02; 451.11; 263.88; -251.43;17.86; 19.76; 1h33m20s; 47m54s; 44m56s; 24.32; 22.37; 26.39; \n\n```\n\nGet statistics for a number of files into a csv output:\n\n```sh\n~$  ./gpsa -out-file=gps-statistics.csv my/test/*.gpx\n\n```\n\nGet statistics for a number of files into a csv output, with verbose comandline output:\n\n```sh\n~$  ./gpsa -verbose -out-file=gps-statistics.csv my/test/*.gpx\nCall:  ./gpsa -verbose -out-file=gps-statistics.csv my/test/01.gpx my/test/02.gpx my/test/03.gpx\nVersion: 2.0.1+7b79520\nRead file: my/test/01.gpx\nRead file: my/test/02.gpx\nRead file: my/test/03.gpx\n3 of 3 files process successfull\n\n```\n\nGet only the summary report out of a bunch of files\n\n```sh\n./bin/gpsa -summary=only my/test/*.gpx\nName; StartTime; EndTime; TrackTime (hh:mm:ss); Distance (km); HorizontalDistance (km); AltitudeRange (m); MinimumAltitude (m); MaximumAltitude (m); ElevationGain (m); ElevationLose (m); UpwardsDistance (km); DownwardsDistance (km); MovingTime (hh:mm:ss); UpwardsTime (hh:mm:ss); DownwardsTime (hh:mm:ss); AverageSpeed (km/h); UpwardsSpeed (km/h); DownwardsSpeed (km/h); \nSum:; -; -; 54:8:43.442; 775.00; 770.48; -; -; -; 7033.35; -6989.57; 309.34; 359.75; 32:47:16.514; 14:19:21.328; 13:33:19.262; -; -; -; \nAverage:; -; -; 2:15:21.810083333; 32.29; 32.10; 134.81; -; -; 293.06; -291.23; 12.89; 14.99; 1:21:58.188083333; 35:48.388666666; 33:53.302583333; 23.78; 21.86; 26.65; \nMinimum:; Sunday, 01-Mar-20 09:27:27 UTC; Sunday, 01-Mar-20 15:11:19 UTC; 53:3; 21.13; 21.07; 63.72; 287.46; 359.73; 159.59; -141.38; 7.92; 8.79; 51:18.444; 21:56.828; 18:22.126; 21.28; 17.73; 23.75; \nMaximum:; Saturday, 31-Oct-20 13:01:16 UTC; Saturday, 31-Oct-20 14:31:42 UTC; 6:4:25; 68.74; 66.54; 801.99; 486.48; 1288.47; 1747.38; -1754.86; 26.45; 34.71; 3:13:47.838; 1:29:31.416; 1:20:40.686; 25.58; 23.78; 28.73;\n\n```\n\nGet statistics from a file as json on stdout\n\n```sh\n./bin/gpsa  -std-out-format=json my/test/02.gpx \n{\n \"Statistics\": [\n  {\n   \"Name\": \"my/test/02.gpx: 2019-08-18 11:07:40\",\n   \"Data\": {\n    \"Distance\": 37823.344979382266,\n    \"HorizontalDistance\": 37741.53944560436,\n    \"MinimumAltitude\": 347.02,\n    \"MaximumAltitude\": 451.11,\n    \"ElevationGain\": 263.88007,\n    \"ElevationLose\": -251.43008,\n    \"UpwardsDistance\": 17858.070360985712,\n    \"DownwardsDistance\": 19761.009730234404,\n    \"TimeDataValid\": true,\n    \"StartTime\": \"2019-08-18T09:11:01Z\",\n    \"EndTime\": \"2019-08-18T15:47:34Z\",\n    \"MovingTime\": 5600000000000,\n    \"UpwardsTime\": 2874000000000,\n    \"DownwardsTime\": 2696000000000,\n    \"Duration\": 23793000000000,\n    \"AverageSpeed\": 6.754168746318261,\n    \"UpwardsSpeed\": 6.213664008693707,\n    \"DownwardsSpeed\": 7.3297513836181025,\n    \"AltitudeRange\": 104.08999633789062\n   }\n  }\n ],\n \"Summary\": null\n```\n\nGet statistics from a file as markdown on stdout\n\n```sh\n./bin/gpsa -std-out-format MD  my/test/02.gpx         \n| Name | StartTime | EndTime | TrackTime (xxhxxmxxs) | Distance (km) | HorizontalDistance (km) | AltitudeRange (m) | MinimumAltitude (m) | MaximumAltitude (m) | ElevationGain (m) | ElevationLose (m) | UpwardsDistance (km) | DownwardsDistance (km) | MovingTime (xxhxxmxxs) | UpwardsTime (xxhxxmxxs) | DownwardsTime (xxhxxmxxs) | AverageSpeed (km/h) | UpwardsSpeed (km/h) | DownwardsSpeed (km/h) |\n|  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |  :----:  |\n| my/test/02.gpx: 2019-08-18 11:07:40 | 2019-08-18T09:11:01Z | 2019-08-18T15:47:34Z | 6h36m33s | 37.82 | 37.74 | 104.09 | 347.02 | 451.11 | 263.88 | -251.43 | 17.86 | 19.76 | 1h33m20s | 47m54s | 44m56s | 24.32 | 22.37 | 26.39 |\n```\n\n\nIt is also possible to pipe in some file names instead of using the file names as input parameter\n\n```sh\nfind ./testdata/valid-gpx -name \"*.gpx\" | ./bin/gpsa -summary=additional -out-file=./test.json\n```\n\nAnd you can pipe in file contents as well\n\n```sh\ncat  01.gpx 01.tcx 03.tcx 02.gpx | ./bin/gpsa -out-file=./test.json\n```\n\n\n#### Output Values explained\n\nBelow is a list of the output values and what they mean:\n\n- `Name`: The name of the output line. Either read from the file, or if no name tag is set in the file it will be calculated out of the filename and the file hierarchy.\n- `StartTime`: The time the track started. *not valid* in case we detect no or invalid time data.\n- `EndTime`: The time the track ended. *not valid* in case we detect no or invalid time data.\n- `TrackTime`: The time between `StartTime` and `EndTime`. *not valid* in case we detect no or invalid time data.\n  - Formatted as `hh:mm:ss` in case of csv output\n  - Measured in `ns` (nano seconds) in case of json output\n- `Distance`: The distance of the track measured in `km`.\n- `HorizontalDistance`: The horizontal distance of the track measured in `km`. This value ignores the vertical component of the distance like most GPS tools do.\n- `AltitudeRange`: The range between the highest and the lowest point. Measured in `m`.\n- `MinimumAltitude`: The altitude of the lowest point. Measured in `m`.\n- `MaximumAltitude`: The altitude of the highest point. Measured in `m`.\n- `ElevationGain`: The total sum of all upwards vertical distance.  Measured in `m`.\n- `ElevationLose`: The total sum of all downwards vertical distance.  Measured in `m`.\n- `UpwardsDistance`: The total sum of all distance moved upwards.  Measured in `km`.\n- `DownwardsDistance`: The total sum of all distance moved downwards.  Measured in `km`.\n- `MovingTime`: The time spend moving. *not valid* in case we detect no or invalid time data.\n  - Formatted as `hh:mm:ss` in case of csv output\n  - Measured in `ns` (nano seconds) in case of json output\n- `UpwardsTime`: The time spend moving upwards. *not valid* in case we detect no or invalid time data.\n  - Formatted as `hh:mm:ss` in case of csv output\n  - Measured in `ns` (nano seconds) in case of json output\n- `DownwardsTime`: The time spend downwards. *not valid* in case we detect no or invalid time data.\n  - Formatted as `hh:mm:ss` in case of csv output\n  - Measured in `ns` (nano seconds) in case of json output\n- `AverageSpeed`: The average speed. Calculated from `Distance` and `MovingTime`.  *not valid* in case we detect no or invalid time data.\n  - Measured in  `km/h`in case of csv output\n  - Measured in  `m/s`in case of json output  \n- `UpwardsSpeed`: The average speed during upwards movement . *not valid* in case we detect no or invalid time data.\n  - Measured in  `km/h`in case of csv output\n  - Measured in  `m/s`in case of json output  \n- `DownwardsSpeed`: The average speed during downwards movement . *not valid* in case we detect no or invalid time data.\n  - Measured in  `km/h`in case of csv output\n  - Measured in  `m/s`in case of json output  \n\nThe statistic summary report will include `-` (in case of csv output) or `0.0000` (in case of json output) for statistic values that make no sense. For example it will not calculate a sum out of speed values or the average out of time stamps.\n\n## Development\n\nTo develop this software install [Go v1.17](https://golang.org/) on your machine.\n\n### Build\n\nUse the [mage](https://magefile.org/) base build script to build and test the project.\n\n```sh\n./build.sh build        # build the project\n./build.sh build test   # build and run the tests for the project\n./build.sh test         # test the project\n```\n\n**Remark:** On Windows replace `./build.sh` with `.\\build.bat`\n\n### Hints for VSCode Users\n\nIf you use [VS Code](https://code.visualstudio.com/) for GO development, you might find the following example settings useful.\n\nThe ```tasks.json```:\n\n```json\n{\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"Build\",\n            \"type\": \"shell\",\n            \"command\": \"${workspaceRoot}/build.sh build test\",\n            \"group\": {\n                \"kind\": \"build\",\n                \"isDefault\": true\n            }\n        },\n        {\n            \"label\": \"Test\",\n            \"type\": \"shell\",\n            \"command\": \"${workspaceRoot}/build.sh test\",\n            \"group\": {\n                \"kind\": \"test\",\n                \"isDefault\": true\n            }\n        }\n    ]\n}\n```\n\nThe ```launch.json```:\n\n```json\n{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"debug\",\n            \"type\": \"go\",\n            \"request\": \"launch\",\n            \"mode\": \"debug\",\n            \"program\": \"${workspaceRoot}/src/tobi.backfrak.de/cmd/gpsa/main.go\",\n            \"cwd\": \"${workspaceRoot}\",\n            \"args\": [\n          //      \"-dont-panic=false\",\n                \"-out-file=/dev/shm/test.csv\",\n                \"${workspaceRoot}/testdata/valid-gpx/02.gpx\"\n            ]\n        }\n    ]\n}\n```\n\nThe ```settings.json```:\n\n```json\n{\n      \"go.gopath\": \"${env:GOPATH}:${workspaceFolder}\",\n}\n```\n\n## Geo Math Internals\n\nThe Geografic calculations are done with the  ```haversine formula```  as described [here](http://www.movable-type.co.uk/scripts/latlong.html). My implementation will ignore altitude differences for distances bigger than 33km by checking the angular distance which in this case then is bigger than 0.3°. For smaller distances the program will add the altitude difference using the ```pythagoras theorem```.\n\n## License\n\ngpsa is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).\nMay got some testfiles and ideas from [gpxgo](https://github.com/tkrajina/gpxgo/tree/master/test_files)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimker25%2Fgpsa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimker25%2Fgpsa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimker25%2Fgpsa/lists"}