Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
3642d64505 | |||
59a829c428 | |||
3f777b7e55 | |||
628088918b | |||
e0e7dbd0e5 | |||
c9620394de | |||
67db75ece8 | |||
6cab491721 | |||
905ac497e1 | |||
07ca626ca8 | |||
2f94211507 | |||
0998371ad6 | |||
a9453dd51e | |||
98c5cad858 | |||
2ad17eab2a | |||
b816d04215 | |||
58ae86db7e | |||
0ae188a0ec |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@ testdata
|
||||
testsource
|
||||
testdest
|
||||
__pycache__
|
||||
Pipfile.lock
|
||||
.vscode
|
||||
|
10
CHANGELOG.md
10
CHANGELOG.md
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.3.2] - 2020-04-11
|
||||
|
||||
### Added
|
||||
- Added additional Exif and ITPC data fields for radiation comment.
|
||||
|
||||
## [0.3.1] - 2020-04-03
|
||||
|
||||
### Added
|
||||
- Prepared pipenv virtual environment.
|
||||
|
||||
## [0.3] - 2020-03-23
|
||||
|
||||
Major rewrite following OOP style. Adds GPS/GPX handling.
|
||||
|
34
CONTRIBUTING.md
Normal file
34
CONTRIBUTING.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# How to contribute
|
||||
|
||||
I'm really glad you're reading this, if you are willing to contribute to this project in some form.
|
||||
This is a quite small project with relatively low complexity so conventions are not as strict as they might be elsewhere. I am keen to learn whether and how this thing was useful to you, where you had problems and what you think could be improved.
|
||||
|
||||
Here are some important resources:
|
||||
|
||||
* This [Blogpost](https://www.commander1024.de/wordpress/2020/03/fotos-mit-daten-zu-radioaktiver-strahlung-taggen) tells you about intention and scope for this tool (in German).
|
||||
* For questions and suggestions, you can [E-Mail](mailto:commander@commander1024.de) me directly.
|
||||
* Bugs? [Gitlab](https://git.commander1024.de/Commander1024/radiation-tager/issues) is where to report them.
|
||||
|
||||
## Submitting changes
|
||||
|
||||
Please send a [Pull Request to radiation_tagger](https://git.commander1024.de/Commander1024/radiation-tager/pulls) in the develop branch with a clear list of what you've done (read more about [pull requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)). Please follow our coding conventions (below) and make sure all of your commits are atomic (one feature per commit).
|
||||
Keep in mind that I am a bloody beginner and probably make more mistakes than you, so I am always open for improvements.
|
||||
|
||||
Always write a clear log message for your commits. One-line messages are fine for small changes, but bigger changes should look like this:
|
||||
|
||||
$ git commit -m "A brief summary of the commit
|
||||
>
|
||||
> A paragraph describing what changed and its impact."
|
||||
|
||||
## Coding conventions
|
||||
|
||||
Start reading the code and you'll get the hang of it. We optimize for readability:
|
||||
|
||||
* We indent using 4 spaces (soft tabs).
|
||||
* We use "describing" variables with underscores like 'position_list'.
|
||||
* Classes and functions go to functions.py to keep the main program small and easy to understand.
|
||||
* We generally follow the Python 3 coding style guidelines.
|
||||
* This is open source software. Consider the people who will read your code, and make it look nice for them. It's sort of like driving a car: Perhaps you love doing donuts when you're alone, but with passengers the goal is to make the ride as smooth as possible.
|
||||
|
||||
Thanks,
|
||||
Commander1024
|
15
Pipfile
Normal file
15
Pipfile
Normal file
@@ -0,0 +1,15 @@
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
pylint = "*"
|
||||
|
||||
[packages]
|
||||
pytz = "*"
|
||||
gpxpy = "*"
|
||||
py3exiv2 = "*"
|
||||
|
||||
# [requires]
|
||||
# python_version = "3.8"
|
31
Readme.md
31
Readme.md
@@ -8,15 +8,32 @@ It can parse a .his (CSV) file from a [GeigerLog](https://sourceforge.net/projec
|
||||
|
||||
It can optionally read a gpx-file, compare the timestamps to 'DateTimeOriginal' and determine closest-matching latitude / longitude / altitude. Timestamps in GPX files are ususally stored in UTC timezone, you can set --timezone to match the local timezone, your camera / geiger counter ran at.
|
||||
|
||||
It then creates a `UserComment` with the actual measured radiation at the time the photo has been taken and writes the geocoordinates into the appropiate Exif tags.
|
||||
It then creates some Exif/ITPC/XMP Comment/Description tags with the actual measured radiation at the time the photo has been taken and writes the geocoordinates into the appropiate Exif tags.
|
||||
|
||||
## Dependencies
|
||||
Right now it depends on the following non-core Python 3 libraries:
|
||||
Right now it depends on the following non-core Python 3 libraries. These can be installed using the package manager of your distribution.
|
||||
|
||||
* [py3exiv2](https://pypi.org/project/py3exiv2/) A Python 3 binding for (lib)exiv2.
|
||||
* [boost.python3](http://www.boost.org/libs/python/doc/index.html) Welcome to Boost.Python, a C++ library which enables seamless interoperability between C++ and the Python programming language.
|
||||
* [exiv2](http://www.exiv2.org/) Exiv2 is a Cross-platform C++ library and a command line utility to manage image metadata.
|
||||
* [gpxpy](https://github.com/tkrajina/gpxpy) gpx-py is a python GPX parser. GPX (GPS eXchange Format) is an XML based file format for GPS tracks.
|
||||
* [pytz](https://pypi.org/project/pytz/) World timezone definitions, modern and historical.
|
||||
* [gpxpy](https://pypi.org/project/gpxpy/) gpx-py is a python GPX parser. GPX (GPS eXchange Format) is an XML based file format for GPS tracks.
|
||||
|
||||
### Setting up a virtual environment using pipenv
|
||||
|
||||
If you prefer to use more updated versions of the dependencies or you do not want to use Python dependencies into your system, I prepared a pipenv virtual environment for you.
|
||||
|
||||
Using `pipenv install` all dependencies will be installed automatically. With `pipenv shell` you can source the venv.
|
||||
|
||||
For py3exivv2 to work / compile the following dependencies must be installed - preferably from your system's package manager:
|
||||
|
||||
* [exiv2](http://www.exiv2.org/) and it's development package. Exiv2 is a Cross-platform C++ library and a command line utility to manage image metadata.
|
||||
* [boost](https://www.boost.org/) and it's development package. Boost provides free peer-reviewed portable C++ source libraries.
|
||||
* [boost.python3](http://www.boost.org/libs/python/doc/index.html) and it's development package. A C++ library which enables seamless interoperability between C++ and the Python programming language.
|
||||
|
||||
#### Debian / Ubuntu
|
||||
sudo apt install pipenv build-essential python-all-dev libexiv2-dev libboost-python-dev
|
||||
|
||||
#### Fedora
|
||||
sudo dnf install pipenv exiv2-devel boost-devel boost-python3-devel make automake gcc gcc-c++
|
||||
|
||||
## Requirements
|
||||
* A bunch of images (jpg, cr2, etc.) with its time of creation stored in `DateTimeOriginal`.
|
||||
@@ -39,7 +56,7 @@ usage: rad_tag.py [-h] [-si SIFACTOR] [-tz Timezone] [-d] [-g GPX] [-o OUTDIR]
|
||||
CSV Photo [Photo ...]
|
||||
|
||||
A unix-tyle tool that extracts GPS and/or radiation data from GPX/CSV files
|
||||
and writes them into the Exif tags of given photos.
|
||||
and writes them into the Exif/ITPC/XMP tags of given photos.
|
||||
|
||||
positional arguments:
|
||||
CSV Geiger counter history file in CSV format.
|
||||
@@ -127,7 +144,7 @@ Once imported, you can export the history into a hisdb.his-file, which is basica
|
||||
|
||||
## GPS setup
|
||||
|
||||
Especially if you use a mobile phone for GPS-logging. Take care, the app can use GPS when turned off, and let it write position sufficiently often. Threshold is 5 minutes by default, but precision will improve when logging more often. Especially "inactivity detection" might become a problem, when staying at one place for a period of time.
|
||||
Especially if you use a mobile phone for GPS-logging, ensure the app can use GPS when the phone is locked. Let it write position sufficiently often. Threshold is 5 minutes by default, but precision will improve when logging more often. Especially "inactivity detection" might become a problem, when staying at one place for a period of time.
|
||||
|
||||
## future possibilities
|
||||
|
||||
|
124
functions.py
124
functions.py
@@ -11,12 +11,13 @@ import pyexiv2
|
||||
|
||||
class Radiation:
|
||||
'''
|
||||
Reiceives values vom CSV file and creates a list of the relevant data
|
||||
Receives values vom CSV file and creates a list of the relevant data
|
||||
|
||||
Arguments:
|
||||
timestamp: Date/time string from CSV as string
|
||||
radiation: Radiation from CSV in CP/M as float
|
||||
local_timezone: timezone for timezone-unware CSV / Photo, if GPX is timezone aware
|
||||
local_timezone: timezone for timezone-unaware CSV / Photo, if GPX is
|
||||
timezone aware
|
||||
si_factor: CP/M to (µS/h) conversion factor - specific to GMC-tube
|
||||
|
||||
Returns:
|
||||
@@ -24,7 +25,13 @@ class Radiation:
|
||||
radiation: radiation in µS/h as str (for Exif comment, UTF-8)
|
||||
'''
|
||||
|
||||
def __init__(self, timestamp, radiation, local_timezone, si_factor):
|
||||
def __init__(
|
||||
self,
|
||||
timestamp,
|
||||
radiation,
|
||||
local_timezone,
|
||||
si_factor
|
||||
):
|
||||
self.timestamp = self._time_conversion(timestamp, local_timezone)
|
||||
self.radiation = self._radiation_conversion(radiation, si_factor)
|
||||
|
||||
@@ -34,7 +41,7 @@ class Radiation:
|
||||
def _time_conversion(self, timestamp, local_timezone):
|
||||
csv_naive_time = datetime.fromisoformat(timestamp)
|
||||
# Set timezone
|
||||
csv_aware_time = csv_naive_time.astimezone(local_timezone)
|
||||
csv_aware_time = csv_naive_time.localize(local_timezone)
|
||||
return csv_aware_time
|
||||
|
||||
def _radiation_conversion(self, radiation, si_factor):
|
||||
@@ -48,9 +55,10 @@ class Photo:
|
||||
|
||||
Arguments:
|
||||
photo: source photo ()
|
||||
local_timezone: timezone for timezone-unware CSV / Photo, if GPX is timezone aware
|
||||
local_timezone: timezone for timezone-unaware CSV / Photo, if GPX is
|
||||
timezone aware
|
||||
dest_dir: destination directory where the photo is going to be copied to.
|
||||
dry_run: whether to acutally write (True / False)
|
||||
dry_run: whether to actually write (True / False)
|
||||
|
||||
Returns:
|
||||
get_date: timestamp of photo als datetime object
|
||||
@@ -64,7 +72,10 @@ class Photo:
|
||||
self.get_photo_basename = self._copy_photo(photo, dest_dir, dry_run)[0]
|
||||
|
||||
def __repr__(self):
|
||||
return 'Photo: %s Creation Date: %s' % (str(self.get_photo_basename), str(self.get_date))
|
||||
return 'Photo: %s Creation Date: %s' % (
|
||||
str(self.get_photo_basename),
|
||||
str(self.get_date)
|
||||
)
|
||||
|
||||
def _copy_photo(self, photo, dest_dir, dry_run):
|
||||
# Determine where to work on photo and copy it there if needed.
|
||||
@@ -91,13 +102,13 @@ class Photo:
|
||||
# date.value creates datetime object in pic_naive_time
|
||||
pic_naive_time = date.value
|
||||
# Set timezone
|
||||
pic_aware_time = pic_naive_time.astimezone(local_timezone)
|
||||
pic_aware_time = pic_naive_time.localize(local_timezone)
|
||||
return pic_aware_time
|
||||
|
||||
class Match:
|
||||
'''
|
||||
Receives lists of time / radiation and GPS data and compares it to timestamp.
|
||||
Then returns relevant values matching to time - or None
|
||||
Receives lists of time / radiation and GPS data and compares it to
|
||||
timestamp.Then returns relevant values matching to time - or None
|
||||
|
||||
Arguments:
|
||||
photo_time: timestamp of photo
|
||||
@@ -110,12 +121,30 @@ class Match:
|
||||
'''
|
||||
|
||||
def __init__(self, photo_time, radiation_list, position_list):
|
||||
self.radiation_value = self._find_radiation_match(photo_time, radiation_list)[1]
|
||||
self.radiation_delta = self._find_radiation_match(photo_time, radiation_list)[0]
|
||||
self.position_delta = self._find_position_match(photo_time, position_list)[0]
|
||||
self.position_latitude = self._find_position_match(photo_time, position_list)[1][1]
|
||||
self.position_longitude = self._find_position_match(photo_time, position_list)[1][2]
|
||||
self.position_altitude = self._find_position_match(photo_time, position_list)[1][3]
|
||||
self.radiation_value = self._find_radiation_match(
|
||||
photo_time,
|
||||
radiation_list
|
||||
)[1]
|
||||
self.radiation_delta = self._find_radiation_match(
|
||||
photo_time,
|
||||
radiation_list
|
||||
)[0]
|
||||
self.position_delta = self._find_position_match(
|
||||
photo_time,
|
||||
position_list
|
||||
)[0]
|
||||
self.position_latitude = self._find_position_match(
|
||||
photo_time,
|
||||
position_list
|
||||
)[1][1]
|
||||
self.position_longitude = self._find_position_match(
|
||||
photo_time,
|
||||
position_list
|
||||
)[1][2]
|
||||
self.position_altitude = self._find_position_match(
|
||||
photo_time,
|
||||
position_list
|
||||
)[1][3]
|
||||
|
||||
def __repr__(self):
|
||||
if self.radiation_value:
|
||||
@@ -171,7 +200,7 @@ class Match:
|
||||
|
||||
class Exif:
|
||||
'''
|
||||
Converts, compiles and writes Exif-Tags from given arguemnts.
|
||||
Converts, compiles and writes Exif/ITPC/XMP-Tags from given arguments.
|
||||
|
||||
Arguments:
|
||||
photo: file name of photo to modify
|
||||
@@ -179,16 +208,28 @@ class Exif:
|
||||
latitude: latitude as float
|
||||
longitude: longitude as float
|
||||
elevation: elevation as float
|
||||
dry_run: whether to acutally write (True / False)
|
||||
dry_run: whether to actually write (True / False)
|
||||
|
||||
Returns:
|
||||
Latitude / Longitude: in degrees
|
||||
Exif-Comment: that has been written (incl. radiation)
|
||||
'''
|
||||
|
||||
def __init__(self, photo, dry_run, radiation, latitude, longitude, elevation):
|
||||
self.write_exif = self._write_exif(photo, dry_run, radiation, latitude,
|
||||
longitude, elevation)
|
||||
def __init__(
|
||||
self, photo,
|
||||
dry_run,
|
||||
radiation,
|
||||
latitude,
|
||||
longitude,
|
||||
elevation
|
||||
):
|
||||
self.write_exif = self._write_exif(
|
||||
photo,
|
||||
dry_run,
|
||||
radiation,
|
||||
latitude,
|
||||
longitude, elevation
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return 'Position: %s, %s: %s ' % self.write_exif
|
||||
@@ -207,7 +248,15 @@ class Exif:
|
||||
second = round((t1 - minute) * 60, 5)
|
||||
return (deg, minute, second, loc_value)
|
||||
|
||||
def _write_exif(self, photo, dry_run, radiation, latitude, longitude, elevation):
|
||||
def _write_exif(
|
||||
self,
|
||||
photo,
|
||||
dry_run,
|
||||
radiation,
|
||||
latitude,
|
||||
longitude,
|
||||
elevation
|
||||
):
|
||||
|
||||
metadata = pyexiv2.ImageMetadata(photo)
|
||||
metadata.read()
|
||||
@@ -217,12 +266,16 @@ class Exif:
|
||||
longitude_degree = self._to_degree(longitude, ["W", "E"])
|
||||
|
||||
# convert decimal coordinates into fractions required for pyexiv2
|
||||
exiv2_latitude = (Fraction(latitude_degree[0] * 60 + latitude_degree[1], 60),
|
||||
Fraction(int(round(latitude_degree[2] * 100, 0)), 6000),
|
||||
Fraction(0, 1))
|
||||
exiv2_longitude = (Fraction(longitude_degree[0] * 60 + longitude_degree[1], 60),
|
||||
Fraction(int(round(longitude_degree[2] * 100, 0)), 6000),
|
||||
Fraction(0, 1))
|
||||
exiv2_latitude = (
|
||||
Fraction(latitude_degree[0] * 60 + latitude_degree[1], 60),
|
||||
Fraction(int(round(latitude_degree[2] * 100, 0)), 6000),
|
||||
Fraction(0, 1)
|
||||
)
|
||||
exiv2_longitude = (
|
||||
Fraction(longitude_degree[0] * 60 + longitude_degree[1], 60),
|
||||
Fraction(int(round(longitude_degree[2] * 100, 0)), 6000),
|
||||
Fraction(0, 1)
|
||||
)
|
||||
|
||||
# Exif tags to write
|
||||
metadata['Exif.GPSInfo.GPSLatitude'] = exiv2_latitude
|
||||
@@ -243,7 +296,11 @@ class Exif:
|
||||
if radiation:
|
||||
# Set new UserComment
|
||||
new_comment = 'Radiation ☢ : %s µS/h' % str(round(radiation, 2))
|
||||
|
||||
metadata['Exif.Photo.UserComment'] = new_comment
|
||||
metadata['Exif.Image.ImageDescription'] = new_comment
|
||||
metadata['Iptc.Application2.Caption'] = [new_comment]
|
||||
metadata['Xmp.dc.description'] = new_comment
|
||||
else:
|
||||
new_comment = None
|
||||
|
||||
@@ -255,7 +312,8 @@ class Exif:
|
||||
|
||||
class Output:
|
||||
'''
|
||||
Receives values to be printed, formats them and returns a string for printing.
|
||||
Receives values to be printed, formats them and returns a string for
|
||||
printing.
|
||||
|
||||
Arguments:
|
||||
radiation: radiation as float
|
||||
@@ -268,7 +326,12 @@ class Output:
|
||||
'''
|
||||
|
||||
def __init__(self, radiation, latitude, longitude, altitude):
|
||||
self.get_string = self._get_string(radiation, latitude, longitude, altitude)
|
||||
self.get_string = self._get_string(
|
||||
radiation,
|
||||
latitude,
|
||||
longitude,
|
||||
altitude
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return self.get_string
|
||||
@@ -294,4 +357,3 @@ class Output:
|
||||
|
||||
# Return data string
|
||||
return data
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 199 KiB |
135
rad_tag.py
135
rad_tag.py
@@ -1,10 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
''' Iterates over a bunch of .jpg or .cr2 files and matches
|
||||
DateTimeOriginal from Exif tag to DateTime in a csv log
|
||||
of a GeigerMuellerCounter and writes its value to the UserComment
|
||||
Exif tag in µS/h '''
|
||||
'''
|
||||
Iterates over a bunch of .jpg or .cr2 files and matches
|
||||
DateTimeOriginal from Exif tags to DateTime in a csv log
|
||||
of a GeigerMuellerCounter and writes its value to Exif/ITPC/XMP tags in µS/h
|
||||
'''
|
||||
|
||||
import csv
|
||||
import argparse
|
||||
@@ -22,26 +23,57 @@ from functions import Radiation, Photo, Match, Exif, Output
|
||||
# 600+ series: 0.002637 µSv/h / CPM
|
||||
|
||||
# Configure argument parser for cli options
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
description='''A unix-tyle tool that
|
||||
extracts GPS and/or radiation data from GPX/CSV files and writes
|
||||
them into the Exif tags of given photos.''')
|
||||
parser.add_argument('-si', '--sifactor', type=float, default=0.0065,
|
||||
help='Factor to multiply recorded CPM with.')
|
||||
parser.add_argument('-tz', '--timezone', type=str, metavar='Timezone', default='utc',
|
||||
help='''Manually set timezone of CSV / and Photo timestamp,
|
||||
defaults to UTC if omitted. This is useful, if the GPS-Logger
|
||||
saves the time incl. timezone''')
|
||||
parser.add_argument('-d', '--dry', action='store_true',
|
||||
help='Dry-run, do not actually write anything.')
|
||||
parser.add_argument('csv', metavar='CSV', type=str,
|
||||
help='Geiger counter history file in CSV format.')
|
||||
parser.add_argument('-g', '--gpx', metavar='GPX', type=str,
|
||||
help='GPS track in GPX format')
|
||||
parser.add_argument('photos', metavar='Photo', type=str, nargs='+',
|
||||
help='One or multiple photo image files to process.')
|
||||
parser.add_argument('-o', '--outdir', type=str, default='.',
|
||||
help='Directory to output processed photos.')
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
description='''A unix-tyle tool that extracts GPS and/or radiation data
|
||||
from GPX/CSV files and writes them into the Exif/ITPC/XMP tags of given
|
||||
photos.'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-si', '--sifactor',
|
||||
type=float,
|
||||
default=0.0065,
|
||||
help='Factor to multiply recorded CPM with.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-tz', '--timezone',
|
||||
type=str,
|
||||
metavar='Timezone',
|
||||
default='utc',
|
||||
help='''Manually set timezone of CSV / and Photo timestamp, defaults to
|
||||
UTC if omitted. This is useful, if the GPS-Logger saves the time in local
|
||||
time (without timezone).'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-d', '--dry',
|
||||
action='store_true',
|
||||
help='Dry-run, do not actually write anything.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'csv',
|
||||
metavar='CSV',
|
||||
type=str,
|
||||
help='Geiger counter history file in CSV format.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-g', '--gpx',
|
||||
metavar='GPX',
|
||||
type=str,
|
||||
help='GPS track in GPX format'
|
||||
)
|
||||
parser.add_argument(
|
||||
'photos',
|
||||
metavar='Photo',
|
||||
type=str,
|
||||
nargs='+',
|
||||
help='One or multiple photo image files to process.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-o', '--outdir',
|
||||
type=str,
|
||||
default='.',
|
||||
help='Directory to output processed photos.'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -54,12 +86,21 @@ position_list = []
|
||||
|
||||
# Import GeigerCounter log
|
||||
with open(args.csv, "r") as f:
|
||||
csv = csv.reader(filter(lambda row: row[0] != '#', f),
|
||||
delimiter=',', skipinitialspace=True)
|
||||
# Read csv file, filter out lines beginning with #
|
||||
csv = csv.reader(
|
||||
filter(lambda row: row[0] != '#', f),
|
||||
delimiter=',',
|
||||
skipinitialspace=True
|
||||
)
|
||||
|
||||
# Import only relevant values, thats timestamp and CP/M
|
||||
# Import only relevant values, that's timestamp and CP/M
|
||||
for _, csv_raw_time, csv_raw_cpm, _ in csv:
|
||||
radiation = Radiation(csv_raw_time, csv_raw_cpm, local_timezone, args.sifactor)
|
||||
radiation = Radiation(
|
||||
csv_raw_time,
|
||||
csv_raw_cpm,
|
||||
local_timezone,
|
||||
args.sifactor
|
||||
)
|
||||
radiation_list.append(radiation)
|
||||
# close CSV file
|
||||
f.close()
|
||||
@@ -71,9 +112,13 @@ if args.gpx:
|
||||
for track in gpx_reader.tracks:
|
||||
for segment in track.segments:
|
||||
for point in segment.points:
|
||||
point_aware_time = point.time.astimezone(local_timezone)
|
||||
position = (point_aware_time, point.latitude, point.longitude,
|
||||
point.elevation)
|
||||
point_aware_time = point.time.localize(local_timezone)
|
||||
position = (
|
||||
point_aware_time,
|
||||
point.latitude,
|
||||
point.longitude,
|
||||
point.elevation
|
||||
)
|
||||
position_list.append(position)
|
||||
|
||||
# Inform the user about what is going to happen
|
||||
@@ -88,18 +133,34 @@ else:
|
||||
# Print table header
|
||||
print('{:<15} {:<25} {:<22}'.format('filename', 'date / time', 'Matched Data'))
|
||||
|
||||
# Iterate over list of photos
|
||||
for src_photo in args.photos:
|
||||
# Instantiate photo, copy it to destdir if needed and receive filename to work on
|
||||
# Instantiate photo, copy it to destdir if needed and receive filename
|
||||
# to work on
|
||||
photo = Photo(src_photo, local_timezone, args.outdir, args.dry)
|
||||
|
||||
# Here the matching magic takes place
|
||||
match = Match(photo.get_date, radiation_list, position_list)
|
||||
|
||||
# Formatted output:
|
||||
data = Output(match.radiation_value, match.position_latitude,
|
||||
match.position_longitude, match.position_altitude)
|
||||
print('{:<15} {:<25} {:<22}'.format(photo.get_photo_basename, str(photo.get_date), str(data)))
|
||||
data = Output(
|
||||
match.radiation_value,
|
||||
match.position_latitude,
|
||||
match.position_longitude,
|
||||
match.position_altitude
|
||||
)
|
||||
print(
|
||||
'{:<15} {:<25} {:<22}'.format(photo.get_photo_basename,
|
||||
str(photo.get_date),
|
||||
str(data))
|
||||
)
|
||||
|
||||
# Write exif data
|
||||
Exif(photo.get_photo_filename, args.dry, match.radiation_value,
|
||||
match.position_latitude, match.position_longitude, match.position_altitude)
|
||||
Exif(
|
||||
photo.get_photo_filename,
|
||||
args.dry,
|
||||
match.radiation_value,
|
||||
match.position_latitude,
|
||||
match.position_longitude,
|
||||
match.position_altitude
|
||||
)
|
||||
|
Reference in New Issue
Block a user