-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathread_mod_aerosol_at_a_location.py
161 lines (150 loc) · 7.59 KB
/
read_mod_aerosol_at_a_location.py
1
#!/usr/bin/python'''Module: read_mod_aerosol_at_a_location.py==========================================================================================Disclaimer: The code is for demonstration purposes only. Users are responsible to check for accuracy and revise to fit their objective.Author: Justin Roberts-Pierel, 2015 Organization: NASA ARSETPurpose: To view info about a variety of SDS from a MODIS HDF4 file (or series of files) both generally and at a specific lat/lonSee the README associated with this module for more information.=========================================================================================='''#import necessary modulesfrom pyhdf import SDimport numpy as np#This uses the file "fileList.txt", containing the list of files, in order to read the filestry: fileList=open('fileList.txt','r')except: print('Did not find a text file containing file names (perhaps name does not match)') sys.exit()#loops through all files listed in the text filefor FILE_NAME in fileList: FILE_NAME=FILE_NAME.strip() user_input=input('\nWould you like to process\n' + FILE_NAME + '\n\n(Y/N)') if(user_input == 'N' or user_input == 'n'): continue else: if '3K' in FILE_NAME: #then this is a 3km MODIS file userInput=int(input('Which SDS would you like to view? (Type the number and press enter) \n(1) Optical_Depth_Land_And_Ocean \n(2) Land_Ocean_Quality_Flag \n(3) Image_Optical_Depth_Land_And_Ocean \n(4) Land_Sea_Flag \n')) while userInput not in {1,2,3,4}:#repeats the question if the user does not choose one of the options print('Please try again.') userInput=int(input('Which SDS would you like to view? (Type the number and press enter) \n(1) Optical_Depth_Land_And_Ocean \n(2) Land_Ocean_Quality_Flag \n(3) Image_Optical_Depth_Land_And_Ocean \n(4) Land_Sea_Flag \n')) #Uses a Python dictionary to choose the SDS indicated by the user dataFields=dict([(1,'Optical_Depth_Land_And_Ocean'),(2,'Land_Ocean_Quality_Flag'),(3,'Image_Optical_Depth_Land_And_Ocean'),(4,'Land_Sea_Flag')]) elif 'L2' in FILE_NAME:#Same as above but for 10km MODIS file userInput=int(input('Which SDS would you like to view? (Type the number and press enter) \n(1) Deep_Blue_Aerosol_Optical_Depth_550_Land \n(2) AOD_550_Dark_Target_Deep_Blue_Combined \n(3) AOD_550_Dark_Target_Deep_Blue_Combined_QA_Flag \n')) while userInput not in {1,2,3}: print('Please try again.') userInput=int(input('Which SDS would you like to view? (Type the number and press enter) \n(1) Deep_Blue_Aerosol_Optical_Depth_550_Land \n(2) AOD_550_Dark_Target_Deep_Blue_Combined \n(3) AOD_550_Dark_Target_Deep_Blue_Combined_QA_Flag \n')) dataFields=dict([(1,'Deep_Blue_Aerosol_Optical_Depth_550_Land'),(2,'AOD_550_Dark_Target_Deep_Blue_Combined'),(3,'AOD_550_Dark_Target_Deep_Blue_Combined_QA_Flag')]) SDS_NAME=dataFields[int(userInput)] # The name of the sds to read try: # open the hdf file for reading hdf=SD.SD(FILE_NAME) except: print('Unable to open file: \n' + FILE_NAME + '\n Skipping...') continue # Get lat and lon info lat = hdf.select('Latitude') latitude = lat[:,:] min_lat=latitude.min() max_lat=latitude.max() lon = hdf.select('Longitude') longitude = lon[:,:] min_lon=longitude.min() max_lon=longitude.max() #get SDS, or exit program if SDS is not in the file try: sds=hdf.select(SDS_NAME) except: print('Sorry, your MODIS hdf file does not contain the SDS:',SDS_NAME,'. Please try again with the correct file type.') continue #get scale factor and fill value for data field attributes=sds.attributes() scale_factor=attributes['scale_factor'] fillvalue=attributes['_FillValue'] #get SDS data data=sds.get() #Print the range of latitude and longitude found in the file, then ask for a lat and lon print('The range of latitude in this file is: ',min_lat,' to ',max_lat, 'degrees \nThe range of longitude in this file is: ',min_lon, ' to ',max_lon,' degrees') user_lat=float(input('\nPlease enter the latitude you would like to analyze (Deg. N): ')) user_lon=float(input('Please enter the longitude you would like to analyze (Deg. E): ')) #Continues to ask for lat and lon until the user enters valid values while user_lat < min_lat or user_lat > max_lat: user_lat=float(input('The latitude you entered is out of range. Please enter a valid latitude: ')) while user_lon < min_lon or user_lon > max_lon: user_lon=float(input('The longitude you entered is out of range. Please enter a valid longitude: ')) #calculation to find nearest point in data to entered location (haversine formula) R=6371000#radius of the earth in meters lat1=np.radians(user_lat) lat2=np.radians(latitude) delta_lat=np.radians(latitude-user_lat) delta_lon=np.radians(longitude-user_lon) a=(np.sin(delta_lat/2))*(np.sin(delta_lat/2))+(np.cos(lat1))*(np.cos(lat2))*(np.sin(delta_lon/2))*(np.sin(delta_lon/2)) c=2*np.arctan2(np.sqrt(a),np.sqrt(1-a)) d=R*c #gets (and then prints) the x,y location of the nearest point in data to entered location, accounting for no data values x,y=np.unravel_index(d.argmin(),d.shape) print('\nThe nearest pixel to your entered location is at: \nLatitude:',latitude[x,y],' Longitude:',longitude[x,y]) if data[x,y]==fillvalue: print('The value of ',SDS_NAME,'at this pixel is',fillvalue,',(No Value)\n') else: print('The value of ', SDS_NAME,'at this pixel is ',round(data[x,y]*scale_factor,3)) #calculates mean, median, stdev in a 3x3 grid around nearest point to entered location if x < 1: x+=1 if x > data.shape[0]-2: x-=2 if y < 1: y+=1 if y > data.shape[1]-2: y-=2 three_by_three=data[x-1:x+2,y-1:y+2] three_by_three=three_by_three.astype(float) three_by_three[three_by_three==float(fillvalue)]=np.nan nnan=np.count_nonzero(~np.isnan(three_by_three)) if nnan == 0: print ('\nThere are no valid pixels in a 3x3 grid centered at your entered location.') else: three_by_three=three_by_three*scale_factor three_by_three_average=np.nanmean(three_by_three) three_by_three_std=np.nanstd(three_by_three) three_by_three_median=np.nanmedian(three_by_three) if nnan == 1: npixels='is' mpixels='pixel' else: npixels='are' mpixels='pixels' print('\nThere',npixels,nnan,'valid',mpixels,'in a 3x3 grid centered at your entered location.') print('\nThe average value in this grid is: ',round(three_by_three_average,3),' \nThe median value in this grid is: ',round(three_by_three_median,3),'\nThe standard deviation in this grid is: ',round(three_by_three_std,3)) #calculates mean, median, stdev in a 5x5 grid around nearest point to entered location if x < 2: x+=1 if x > data.shape[0]-3: x-=1 if y < 2: y+=1 if y > data.shape[1]-3: y-=1 five_by_five=data[x-2:x+3,y-2:y+3] five_by_five=five_by_five.astype(float) five_by_five[five_by_five==float(fillvalue)]=np.nan nnan=np.count_nonzero(~np.isnan(five_by_five)) if nnan == 0: print ('There are no valid pixels in a 5x5 grid centered at your entered location. \n') else: five_by_five=five_by_five*scale_factor five_by_five_average=np.nanmean(five_by_five) five_by_five_std=np.nanstd(five_by_five) five_by_five_median=np.nanmedian(five_by_five) if nnan == 1: npixels='is' mpixels='pixel' else: npixels='are' mpixels='pixels' print('\nThere',npixels,nnan,' valid',mpixels,' in a 5x5 grid centered at your entered location. \n') print('The average value in this grid is: ',round(five_by_five_average,3),' \nThe median value in this grid is: ',round(five_by_five_median,3),'\nThe standard deviation in this grid is: ',round(five_by_five_std,3))print('\nAll valid files have been processed')