Source code for euring.utils

import re

from .exceptions import EuringParseException


[docs] def euring_dms_to_float(value): """Convert EURING DMS coordinate text into decimal degrees.""" try: seconds = value[-2:] minutes = value[-4:-2] degrees = value[:-4] result = float(degrees) negative = result < 0 result = abs(result) + (float(minutes) / 60) + (float(seconds) / 3600) if negative: result = -result except (IndexError, ValueError): raise EuringParseException('Could not parse coordinate "{value}" to decimal.') return result
[docs] def euring_float_to_dms(value, round_seconds=False): """ Convert a Decimal Degree Value into Degrees Minute Seconds Notation. Pass value as double type = {Latitude or Longitude} as string returns a dict with quadrant, degreees, minutes, seconds created by: anothergisblog.blogspot.com modified by: Dylan Verheul """ degrees = int(value) submin = abs((value - int(value)) * 60) minutes = int(submin) seconds = abs((submin - int(submin)) * 60) if degrees < 0: quadrant = "-" else: quadrant = "+" # includes 0 if round_seconds: seconds = int(round(seconds)) return {"quadrant": quadrant, "degrees": degrees, "minutes": minutes, "seconds": seconds}
[docs] def euring_coord_to_dms(value, degrees_pos): """Format a decimal coordinate into EURING DMS text with fixed degree width.""" dms = euring_float_to_dms(value, round_seconds=True) return "{quadrant}{degrees}{minutes}{seconds}".format( quadrant=dms["quadrant"], degrees="{}".format(abs(dms["degrees"])).zfill(degrees_pos), minutes="{}".format(dms["minutes"]).zfill(2), seconds="{}".format(dms["seconds"]).zfill(2), )
[docs] def euring_lat_to_dms(value): """Convert a latitude in decimal degrees into EURING DMS text.""" return euring_coord_to_dms(value, degrees_pos=2)
[docs] def euring_lng_to_dms(value): """Convert a longitude in decimal degrees into EURING DMS text.""" return euring_coord_to_dms(value, degrees_pos=3)
[docs] def euring_identification_display_format(euring_number): """ Return EURING number in upper case, with anything that is not a letter or digit removed. :param euring_number: :return: """ # Convert to uppercase unicode result = f"{euring_number}".upper() # Remove everything that is not a digit (0-9) or letter (A-Z) return re.sub(r"[^A-Z0-9]", "", result)
[docs] def euring_identification_export_format(euring_number): """ Return EURING code formatted for display and with added internal padding (dots) up to length 10. :param euring_number: :param length: :return: """ # Set length length = 10 # Remove any character that is not a letter or a digit, and convert to upper case text = euring_identification_display_format(euring_number) # If we are at at the requested length, we're done text_length = len(text) if text_length == length: return text if text_length > length: return text[:length] # TODO: Maybe raise ValueError('EURING number too long after euring_display_format ' # '({} {}).'.format(euring_number, text)) # We need length - text_length dots to fill us up dots = "." * (length - text_length) # Insert dots before the rightmost series of digits result = "" digit_seen = False done = False for c in reversed(text): if not done: if c.isdigit(): digit_seen = True elif digit_seen: result = dots + result done = True result = c + result if not done: result = dots + result return result
[docs] def euring_scheme_export_format(scheme_code): """ Proper export format for a scheme code. :param scheme_code: Scheme code (string) :return: Formatted scheme code """ result = f"{scheme_code}".upper() return result[0:3].rjust(3)
[docs] def euring_species_export_format(species_code): """ Proper export format for EURING species code. :param species_code: :return: """ if not species_code: return "00000" # Must be a valid integer try: result = int(species_code) except ValueError: raise ValueError("Invalid EURING species code.") # Now to unicode result = f"{species_code}" # Check the length if len(result) > 5: raise ValueError("EURING species code too long.") # Pad with zeroes and return result return result.zfill(5)