import os import math import pyproj import plio.io.isis_serial_number as sn def line_sample_size(record, path): """ Converts columns l. and s. to sample size, line size, and generates an image index Parameters ---------- record : object Pandas series object path : str Path to the associated sup files for a socet project Returns ------- : list A list of sample_size, line_size, and img_index """ with open(os.path.join(path, record['ipf_file'] + '.sup')) as f: for i, line in enumerate(f): if i == 2: img_index = line.split('\\') img_index = img_index[-1].strip() img_index = img_index.split('.')[0] if i == 3: line_size = line.split(' ') line_size = line_size[-1].strip() assert int(line_size) > 0, "Line number {} from {} is a negative number: Invalid Data".format(line_size, record['ipf_file']) if i == 4: sample_size = line.split(' ') sample_size = sample_size[-1].strip() assert int(sample_size) > 0, "Sample number {} from {} is a negative number: Invalid Data".format(sample_size, record['ipf_file']) break line_size = int(line_size)/2.0 + record['l.'] + 1 sample_size = int(sample_size)/2.0 + record['s.'] + 1 return sample_size, line_size, img_index # converts known to ISIS keywords def known(record): """ Converts the known field from a socet dataframe into the isis point_type column Parameters ---------- record : object Pandas series object Returns ------- : str String representation of a known field """ if record['known'] == 0: return 'Free' elif record['known'] == 1 or record['known'] == 2 or record['known'] == 3: return 'Constrained' # converts +/- 180 system to 0 - 360 system def to_360(num): """ Transforms a given number into 0 - 360 space Parameters ---------- num : int A given integer Returns ------- : int num moduloed by 360 """ return num % 360 def oc2og(dlat, dMajorRadius, dMinorRadius): """ Ocentric to ographic latitudes Parameters ---------- dlat : float Latitude to convert dMajorRadius : float Radius from the center of the body to the equater dMinorRadius : float Radius from the pole to the center of mass Returns ------- dlat : float Converted latitude into ographic space """ try: dlat = math.radians(dlat) dlat = math.atan(((dMajorRadius / dMinorRadius)**2) * (math.tan(dlat))) dlat = math.degrees(dlat) except: print ("Error in oc2og conversion") return dlat def og2oc(dlat, dMajorRadius, dMinorRadius): """ Ographic to ocentric latitudes Parameters ---------- dlat : float Latitude to convert dMajorRadius : float Radius from the center of the body to the equater dMinorRadius : float Radius from the pole to the center of mass Returns ------- dlat : float Converted latitude into ocentric space """ try: dlat = math.radians(dlat) dlat = math.atan((math.tan(dlat) / ((dMajorRadius / dMinorRadius)**2))) dlat = math.degrees(dlat) except: print ("Error in og2oc conversion") return dlat # gets eRadius and pRadius from a .prj file def get_axis(file): """ Gets eRadius and pRadius from a .prj file Parameters ---------- file : str file with path to a given socet project file Returns ------- : list A list of the eRadius and pRadius of the project file """ with open(file) as f: from collections import defaultdict files = defaultdict(list) for line in f: ext = line.strip().split(' ') files[ext[0]].append(ext[-1]) eRadius = float(files['A_EARTH'][0]) pRadius = eRadius * (1 - float(files['E_EARTH'][0])) return eRadius, pRadius def lat_ISIS_coord(record, semi_major, semi_minor): """ Function to convert lat_Y_North to ISIS_lat Parameters ---------- record : object Pandas series object semi_major : float Radius from the center of the body to the equater semi_minor : float Radius from the pole to the center of mass Returns ------- coord_360 : float Converted latitude into ocentric space, and mapped into 0 to 360 """ ocentric_coord = og2oc(record['lat_Y_North'], semi_major, semi_minor) coord_360 = to_360(ocentric_coord) return coord_360 def lon_ISIS_coord(record, semi_major, semi_minor): """ Function to convert long_X_East to ISIS_lon Parameters ---------- record : object Pandas series object semi_major : float Radius from the center of the body to the equater semi_minor : float Radius from the pole to the center of mass Returns ------- coord_360 : float Converted longitude into ocentric space, and mapped into 0 to 360 """ ocentric_coord = og2oc(record['long_X_East'], semi_major, semi_minor) coord_360 = to_360(ocentric_coord) return coord_360 def body_fix(record, semi_major, semi_minor): """ Transforms latitude, longitude, and height of a socet point into a body fixed point Parameters ---------- record : object Pandas series object semi_major : float Radius from the center of the body to the equater semi_minor : float Radius from the pole to the center of mass Returns ------- : list Body fixed lat, lon and height coordinates as lat, lon, ht """ ecef = pyproj.Proj(proj='geocent', a=semi_major, b=semi_minor) lla = pyproj.Proj(proj='latlon', a=semi_major, b=semi_minor) lon, lat, height = pyproj.transform(lla, ecef, record['long_X_East'], record['lat_Y_North'], record['ht']) return lon, lat, height def apply_transformations(atf_dict, df): """ Takes a atf dictionary and a socet dataframe and applies the necessary transformations to convert that dataframe into a isis compatible dataframe Parameters ---------- atf_dict : dict Dictionary containing information from an atf file df : object Pandas dataframe object """ prj_file = os.path.join(atf_dict['PATH'], atf_dict['PROJECT'].split('\\')[-1]) eRadius, pRadius = get_axis(prj_file) df['s.'], df['l.'], df['image_index'] = (zip(*df.apply(line_sample_size, path = atf_dict['PATH'], axis=1))) df['known'] = df.apply(known, axis=1) df['lat_Y_North'] = df.apply(lat_ISIS_coord, semi_major = eRadius, semi_minor = pRadius, axis=1) df['long_X_East'] = df.apply(lon_ISIS_coord, semi_major = eRadius, semi_minor = pRadius, axis=1) df['long_X_East'], df['lat_Y_North'], df['ht'] = zip(*df.apply(body_fix, semi_major = eRadius, semi_minor = pRadius, axis = 1)) def serial_numbers(image_dict, path): """ Creates a dict of serial numbers with the cub being the key Parameters ---------- images : list path : str extension : str Returns ------- serial_dict : dict """ serial_dict = dict() for key in image_dict: snum = sn.generate_serial_number(os.path.join(path, image_dict[key])) snum = snum.replace('Mars_Reconnaissance_Orbiter', 'MRO') serial_dict[key] = snum return serial_dict