''' Author: Kristofer Drozd Date: November 20, 2015 Description: This python script performs calculations to obtain positional parameters (azi & zen) of the spacecraft and sun at the exact moment a picture is taken of the landmark being analyzed. The following text files must be in the same directory in which the code is being run: LMRKNAMES.txt: name of the landmark being analyzed NUMBERPIC.txt: # of pictures taken of landmark RESOLUTION.txt: resolution of each picture PICTIMES.txt: UTC time of each picture LAT.txt: latitude of landmark LON.txt: west longitude of landmark SCOBJ1.txt: x component of space craft to object center vectors (BF frame) SCOBJ2.txt: y component of space craft to object center vectors (BF frame) SCOBJ3.txt: z component of space craft to object center vectors (BF frame) SZ1.txt: x component of object center to sun unit vectors (BF frame) SZ2.txt: y component of object center to sun unit vectors (BF frame) SZ3.txt: z component of object center to sun unit vectors (BF frame) VLM1.txt: x component of object center to landmark vectors (BF frame) VLM2.txt: y component of object center to landmark vectors (BF frame) VLM3.txt: z component of object center to landmark vectors (BF frame) Output: A text file of the name <landmark name>_viewing.txt is created in the directory the code is run ''' import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as mpatches def file_len(fname): ''' This function counts the number of lines in a text file Parameters fname: name of the text file Returns i + 1: number of lines in the text file ''' with open(fname) as f: for i, l in enumerate(f): pass return i + 1 def SCPOS(SCOBJ1, SCOBJ2, SCOBJ3): ''' This function creates the object's center to spacecraft vector in body fixed frame. Since the SCOBJ compoents are from the spacecraft to the object's center, the components are multiplied by -1. Parameters SCOBJ1: x component of SCOBJ SCOBJ2: y component of SCOBJ SCOBGJ: z component of SCOBJ Returns SCOBJ: vector ''' SCPOS = np.array([-SCOBJ1, -SCOBJ2, -SCOBJ3]) return SCPOS def SUNPOS(SZ1, SZ2, SZ3): ''' This function creates the object center to sun vector in body fixed frame. Since SZ is a unit vector it is multuplied by 1 AU. Parameters SZ1: x component of SZ SZ2: y component of SZ SZ3: z component of SZ Returns SCOBJ: vector ''' SZ_au = np.multiply(np.array([ SZ1, SZ2, SZ3]), 1.496e8) return SZ_au def BEN2LMRK(VLM1, VLM2, VLM3): ''' This function creates the object center to landmark vector in body fixed frame. Parameters VLM1: x component of BEN2LMRK VLM2: y component of BEN2LMRK VLM3: z component of BEN2LMRK Returns yomama: vector ''' yomama = np.array([VLM1, VLM2, VLM3], float) return yomama def BF2SEZ_tm(lon,lat): ''' This function creates the Body Fixed frame to SEZ fram transformation matrix. Parameters lon: The east longitude of the landamrk (degrees) lat: The latitude of the landamrk (degreesP) Returns Qxx_mat: The transformation matrix ''' lat_r = np.radians(lat) lon_r = np.radians(lon) Qxx_mat = np.array([[ np.sin(lat_r)*np.cos(lon_r), np.sin(lat_r)*np.sin(lon_r), -np.cos(lat_r)], [-np.sin(lon_r), np.cos(lon_r), 0], [np.cos(lat_r)*np.cos(lon_r), np.cos(lat_r)*np.sin(lon_r),np.sin(lat_r)]]) return Qxx_mat #========================================================== def main(): ''' The various input files are read in, so that their data can be used to calculate the azimuth and zenith angles of the spacecraft and sun with respect to a topcentric NEZ frame centered on the landmark during the exact moment a picture is taken of said landmark. A text file is then created listing the angles, picture resolution, and picture UTC time. ''' ''' Reading in TXT Files ''' fid1 = open('LAT.txt') fid2 = open('LON.txt') fid3 = open('NUMBERPIC.txt') fid4 = open('PICTIMES.txt') fid5 = open('lmrkname.txt') fid6 = open('RESOLUTION.txt') fid7 = open('SCOBJ1.txt') fid8 = open('SCOBJ2.txt') fid9 = open('SCOBJ3.txt') fid10 = open('SZ1.txt') fid11 = open('SZ2.txt') fid12 = open('SZ3.txt') fid13 = open('VLM1.txt') fid14 = open('VLM2.txt') fid15 = open('VLM3.txt') ''' Getting latitude and longitude of landmark ''' lat = float(fid1.readline().rstrip()) lon = 360 - float(fid2.readline().rstrip()) ''' Getting object center to landmark vector components and then vector ''' VLM1 = fid13.readline().rstrip() VLM1 = float(VLM1.replace('D', 'E')) VLM2 = fid14.readline().rstrip() VLM2 = float(VLM2.replace('D', 'E')) VLM3 = fid15.readline().rstrip() VLM3 = float(VLM3.replace('D', 'E')) lmrk_vec = BEN2LMRK(VLM1, VLM2, VLM3) ''' Getting number of pictures and landmark name ''' number_pics = int(fid3.readline().rstrip()) lmrk_name = fid5.readline().rstrip() ''' Formting outputs & creating text file ''' file = open(lmrk_name+"_viewing.txt", "w") file.write( "\n") file.write( lmrk_name) file.write( "\n") file.write( "lat = %f, Elon = %f\n" % (lat, lon)) file.write( "# of pictures taken = %f\n" % (number_pics)) file.write("\n") file.write( "| UTC | res | sun_zen | sun_azi | sc_zen | sc_azi |\n") file.write( "|--------------------------------------------------------------------------------------------|\n") ''' for loop ''' for j in range(0, number_pics): ''' Getting the SCOBJ vector components one line at a time ''' SCOBJ1 = fid7.readline().rstrip() SCOBJ1 = float(SCOBJ1.replace('D', 'E')) SCOBJ2 = fid8.readline().rstrip() SCOBJ2 = float(SCOBJ2.replace('D', 'E')) SCOBJ3 = fid9.readline().rstrip() SCOBJ3 = float(SCOBJ3.replace('D', 'E')) ''' Getting the SZ vector components one line at a time ''' SZ1 = fid10.readline().rstrip() SZ1 = float(SZ1.replace('D', 'E')) SZ2 = fid11.readline().rstrip() SZ2 = float(SZ2.replace('D', 'E')) SZ3 = fid12.readline().rstrip() SZ3 = float(SZ3.replace('D', 'E')) ''' Getting picture resolution one line at a time ''' res = float(fid6.readline().rstrip()) ''' Getting UTC time of each picture one line at a time ''' time = fid4.readline().rstrip() ''' SC Calculations lmrk2sc_vec: landmark to sc vector in body fixed frame n_sc: landmark to sc vector in topographical SEZ frame elvation_sc: elevation angle of n_sc zenith_sc: zenith angle of n_sc azimuth_sc: azimuth angle of n_sc, but manipulated so it is in NEZ frame opposed to SEZ ''' lmrk2sc_vec = np.subtract(SCPOS(SCOBJ1, SCOBJ2, SCOBJ3),lmrk_vec) n_sc = np.dot(BF2SEZ_tm(lon,lat),lmrk2sc_vec) elevation_sc = np.degrees(np.arcsin(np.true_divide(n_sc[2],np.linalg.norm(n_sc)))) zenith_sc = 90-elevation_sc azimuth_sc = np.degrees(np.arctan2(n_sc[1],-n_sc[0])) if azimuth_sc < 0: azimuth_sc = 360+azimuth_sc else: azimuth_sc = azimuth_sc ''' Sun Calculations lmrk2sun_vec: landmark to sun vector in body fixed frame n_sun: landmark to sun vector in topographical SEZ frame elvation_sun: elevation angle of n_sun zenith_sun: zenith angle of n_sun azimuth_sun: azimuth angle of n_sun, but manipulated so it is in NEZ frame opposed to SEZ ''' lmrk2sun_vec = np.subtract(SUNPOS(SZ1, SZ2, SZ3),lmrk_vec) n_sun = np.dot(BF2SEZ_tm(lon,lat),lmrk2sun_vec) elevation_sun = np.degrees(np.arcsin(np.true_divide(n_sun[2],np.linalg.norm(n_sun)))) zenith_sun = 90-elevation_sun azimuth_sun = np.degrees(np.arctan2(n_sun[1],-n_sun[0])) if azimuth_sun < 0: azimuth_sun = 360+azimuth_sun else: azimuth_sun = azimuth_sun ''' Continued formatting of text file ''' file.write("| ") file.write(time) file.write(" ") file.write( "| %07.3f | %+08.3f | %08.3f | %+08.3f | %08.3f \n" % (res, zenith_sun, azimuth_sun, zenith_sc, azimuth_sc)) file.close() with open(lmrk_name+"_viewing.txt") as ifh: arr = np.loadtxt(ifh, usecols = (1,2,3,4,5), dtype = float, delimiter = " | ", skiprows = 7) theta = np.linspace(-np.pi, np.pi, 100) azi_sun_1 = arr[:,2] zen_sun_1 = arr[:,1] azi_sc_1 = arr[:,4] zen_sc_1 = arr[:,3] res = arr[:,0] ''' Sun plot ''' plt.figure(1) ax1 = plt.subplot(111, polar = True) ax1.set_theta_zero_location("N") ax1.set_theta_direction(-1) plt.grid(True) ax1.set_rgrids([15,30,45,60,75,90], angle = 60, fontsize = 10) ax1.set_rlim(0, 90) ax1.set_thetagrids([0, 45, 90, 135, 180, 225, 270, 315], frac = 1.08, fontsize = 10) for k in range(0, number_pics): if res[k] >=1: ax1.plot(np.radians(azi_sun_1[k]), zen_sun_1[k], 'or') elif 1 > res[k] and res[k] >= .5: ax1.plot(np.radians(azi_sun_1[k]), zen_sun_1[k], 'og') elif .5 > res[k] and res[k] >= .25: ax1.plot(np.radians(azi_sun_1[k]), zen_sun_1[k], 'ob') elif .25 > res[k] and res[k] >= .1: ax1.plot(np.radians(azi_sun_1[k]), zen_sun_1[k], 'oy') elif .1 > res[k] and res[k] >= .05: ax1.plot(np.radians(azi_sun_1[k]), zen_sun_1[k], 'om') else: ax1.plot(np.radians(azi_sun_1[k]), zen_sun_1[k], 'oc') mot1 = mpatches.Patch( color = 'r', label = 'Res $\geq$ 50 cm') mot2 = mpatches.Patch( color = 'g', label = '100 cm > Res $\geq$ 50 cm') mot3 = mpatches.Patch( color = 'b', label = '50 cm > Res $\geq$ 25 cm') mot4 = mpatches.Patch( color = 'y', label = '25 cm > Res $\geq$ 10 cm') mot5 = mpatches.Patch( color = 'm', label = '10 cm > Res $\geq$ 5 cm') mot6 = mpatches.Patch( color = 'c', label = 'Res < 5 cm') plt.legend( handles = [mot1, mot2, mot3, mot4, mot5, mot6], fontsize = 8, loc = 2, bbox_to_anchor = (.93, 1.1)) figure_title1 = lmrk_name+' Sun Azimuth vs. Zenith' plt.text(.5, 1.08,figure_title1, horizontalalignment = 'center', fontsize = 15, transform = ax1.transAxes) plt.savefig( lmrk_name+'_sun_plot.png') plt.clf() ''' SC plot ''' plt.figure(2) ax2 = plt.subplot(111, polar = True) ax2.set_theta_zero_location("N") ax2.set_theta_direction(-1) plt.grid(True) ax2.set_rgrids([15,30,45,60,75,90], angle = 60, fontsize = 10) ax2.set_rlim(0, 90) ax2.set_thetagrids([0, 45, 90, 135, 180, 225, 270, 315], frac = 1.08, fontsize = 10) for k in range(0, number_pics): if res[k] >=1: ax2.plot(np.radians(azi_sc_1[k]), zen_sc_1[k], 'or') elif 1 > res[k] and res[k] >= .5: ax2.plot(np.radians(azi_sc_1[k]), zen_sc_1[k], 'og') elif .5 > res[k] and res[k] >= .25: ax2.plot(np.radians(azi_sc_1[k]), zen_sc_1[k], 'ob') elif .25 > res[k] and res[k] >= .1: ax2.plot(np.radians(azi_sc_1[k]), zen_sc_1[k], 'oy') elif .1 > res[k] and res[k] >= .05: ax2.plot(np.radians(azi_sc_1[k]), zen_sc_1[k], 'om') else: ax2.plot(np.radians(azi_sc_1[k]), zen_sc_1[k], 'oc') dot1 = mpatches.Patch( color = 'r', label = 'Res $\geq$ 50 cm') dot2 = mpatches.Patch( color = 'g', label = '100 cm > Res $\geq$ 50 cm') dot3 = mpatches.Patch( color = 'b', label = '50 cm > Res $\geq$ 25 cm') dot4 = mpatches.Patch( color = 'y', label = '25 cm > Res $\geq$ 10 cm') dot5 = mpatches.Patch( color = 'm', label = '10 cm > Res $\geq$ 5 cm') dot6 = mpatches.Patch( color = 'c', label = 'Res < 5 cm') plt.legend( handles = [dot1, dot2, dot3, dot4, dot5, dot6], fontsize = 8, loc = 2, bbox_to_anchor = (.93, 1.1)) figure_title2 = lmrk_name+' SC Azimuth vs. Zenith' plt.text(.5, 1.08,figure_title2, horizontalalignment = 'center', fontsize = 15, transform = ax2.transAxes) plt.savefig(lmrk_name+'_sc_plot.png') plt.clf() #print(n_sc) #print(lmrk2sc_vec) #print(elevation_sc) #print(elevation_sun) #print(BF2SEZ_tm(lon,lat)) if __name__ == '__main__': main()