Initial commit
This commit is contained in:
294
Flexbrdf/scripts/configs/image_correct_json_generate.py
Normal file
294
Flexbrdf/scripts/configs/image_correct_json_generate.py
Normal file
@ -0,0 +1,294 @@
|
||||
'''Template script for generating image_correct configuration JSON files.
|
||||
|
||||
These setting are meant only as an example, are not appropriate for
|
||||
all situations and may need to be adjusted
|
||||
'''
|
||||
|
||||
import json
|
||||
import glob
|
||||
import numpy as np
|
||||
|
||||
#Output path for configuration file
|
||||
config_file = "/data1/temp/ht_test/ic_test.json"
|
||||
config_dict = {}
|
||||
|
||||
#Only coefficients for good bands will be calculated
|
||||
config_dict['bad_bands'] =[[300,400],[1337,1430],[1800,1960],[2450,2600]]
|
||||
#config_dict['bad_bands'] =[[300,400],[900,2600]] # Subset for testing
|
||||
|
||||
# Input data settings for NEON
|
||||
#################################################################
|
||||
# config_dict['file_type'] = 'neon'
|
||||
# images= glob.glob("/data1/temp/ht_test/*.h5")
|
||||
# images.sort()
|
||||
# config_dict["input_files"] = images
|
||||
|
||||
# Input data settings for ENVI
|
||||
#################################################################
|
||||
|
||||
''' Only difference between ENVI and NEON settings is the specification
|
||||
of the ancillary datasets (ex. viewing and solar geometry). All hytools
|
||||
functions assume that the ancillary data and the image date are the same
|
||||
size, spatially, and are ENVI formatted files.
|
||||
|
||||
The ancillary parameter is a dictionary with a key per image. Each value
|
||||
per image is also a dictionary where the key is the dataset name and the
|
||||
value is list consisting of the file path and the band number.
|
||||
|
||||
'''
|
||||
|
||||
config_dict['file_type'] = 'envi'
|
||||
aviris_anc_names = ['path_length','sensor_az','sensor_zn',
|
||||
'solar_az', 'solar_zn','phase','slope',
|
||||
'aspect', 'cosine_i','utc_time']
|
||||
images= glob.glob("/data1/temp/ht_test/ang20190707t203417_rfl_v2v2_img")
|
||||
images.sort()
|
||||
config_dict["input_files"] = images
|
||||
|
||||
config_dict["anc_files"] = {}
|
||||
anc_files = glob.glob("/data1/temp/ht_test/ang20190707t203417_rdn_v2v2_obs_ort_corr")
|
||||
anc_files.sort()
|
||||
for i,image in enumerate(images):
|
||||
config_dict["anc_files"][image] = dict(zip(aviris_anc_names,
|
||||
[[anc_files[i],a] for a in range(len(aviris_anc_names))]))
|
||||
|
||||
# Export settings
|
||||
#################################################################
|
||||
''' Options for subset waves:
|
||||
1. List of subset wavelenths
|
||||
2. Empty list, this will output all good bands, if resampler is
|
||||
set it will also resample.
|
||||
- Currently resampler cannot be used in conjuction with option 1
|
||||
'''
|
||||
|
||||
config_dict['export'] = {}
|
||||
config_dict['export']['coeffs'] = True
|
||||
config_dict['export']['image'] = True
|
||||
config_dict['export']['masks'] = True
|
||||
config_dict['export']['subset_waves'] = []
|
||||
config_dict['export']['output_dir'] = "/data1/temp/ht_test/"
|
||||
config_dict['export']["suffix"] = 'anc_nodata_test'
|
||||
|
||||
#Corrections
|
||||
#################################################################
|
||||
''' Specify correction(s) to be applied, corrections will be applied
|
||||
in the order they are specified.
|
||||
|
||||
Options include:
|
||||
|
||||
['topo']
|
||||
['brdf']
|
||||
['glint']
|
||||
['topo','brdf']
|
||||
['brdf','topo']
|
||||
['brdf','topo','glint']
|
||||
[] <---Export uncorrected images
|
||||
|
||||
'''
|
||||
|
||||
config_dict["corrections"] = ['brdf']
|
||||
|
||||
#Topographic Correction options
|
||||
#################################################################
|
||||
'''
|
||||
Types supported:
|
||||
- 'cosine'
|
||||
- 'c'
|
||||
- 'scs
|
||||
- 'scs+c'
|
||||
- 'mod_minneart'
|
||||
- 'precomputed'
|
||||
|
||||
Apply and calc masks are only needed for C and SCS+C corrections. They will
|
||||
be ignored in all other cases and correction will be applied to all
|
||||
non no-data pixels.
|
||||
|
||||
'c_fit_type' is only applicable for the C or SCS+C correction type. Options
|
||||
include 'ols' or 'nnls'. Choosing 'nnls' can limit overcorrection.
|
||||
|
||||
For precomputed topographic coefficients 'coeff_files' is a
|
||||
dictionary where each key is the full the image path and value
|
||||
is the full path to coefficients file, one per image.
|
||||
'''
|
||||
config_dict["topo"] = {}
|
||||
config_dict["topo"]['type'] = 'scs+c'
|
||||
config_dict["topo"]['calc_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.1,'max': 1.0}],
|
||||
['ancillary',{'name':'slope',
|
||||
'min': np.radians(5),'max':'+inf' }],
|
||||
['ancillary',{'name':'cosine_i',
|
||||
'min': 0.12,'max':'+inf' }],
|
||||
['cloud',{'method':'zhai_2018',
|
||||
'cloud':True,'shadow':True,
|
||||
'T1': 0.01,'t2': 1/10,'t3': 1/4,
|
||||
't4': 1/2,'T7': 9,'T8': 9}]]
|
||||
|
||||
config_dict["topo"]['apply_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.1,'max': 1.0}],
|
||||
['ancillary',{'name':'slope',
|
||||
'min': np.radians(5),'max':'+inf' }],
|
||||
['ancillary',{'name':'cosine_i',
|
||||
'min': 0.12,'max':'+inf' }]]
|
||||
config_dict["topo"]['c_fit_type'] = 'nnls'
|
||||
|
||||
# config_dict["topo"]['type'] = 'precomputed'
|
||||
# config_dict["brdf"]['coeff_files'] = {}
|
||||
|
||||
#BRDF Correction options
|
||||
#################################################################3
|
||||
'''
|
||||
Types supported:
|
||||
- 'universal': Simple kernel multiplicative correction.
|
||||
- 'local': Correction by class. (Future.....)
|
||||
- 'flex' : Correction by NDVI class
|
||||
- 'precomputed' : Use precomputed coefficients
|
||||
|
||||
If 'bin_type' == 'user'
|
||||
'bins' should be a list of lists, each list the NDVI bounds [low,high]
|
||||
|
||||
Object shapes ('h/b','b/r') only needed for Li kernels.
|
||||
|
||||
For precomputed topographic coefficients 'coeff_files' is a
|
||||
dictionary where each key is the full the image path and value
|
||||
is the full path to coefficients file, one per image.
|
||||
'''
|
||||
|
||||
config_dict["brdf"] = {}
|
||||
|
||||
# Options are 'line','scene', or a float for a custom solar zn
|
||||
# Custom solar zenith angle should be in radians
|
||||
config_dict["brdf"]['solar_zn_type'] ='scene'
|
||||
|
||||
# Universal BRDF config
|
||||
#----------------------
|
||||
# config_dict["brdf"]['type'] = 'universal'
|
||||
# config_dict["brdf"]['grouped'] = True
|
||||
# config_dict["brdf"]['sample_perc'] = 0.1
|
||||
# config_dict["brdf"]['geometric'] = 'li_dense_r'
|
||||
# config_dict["brdf"]['volume'] = 'ross_thick'
|
||||
# config_dict["brdf"]["b/r"] = 2.5
|
||||
# config_dict["brdf"]["h/b"] = 2
|
||||
# config_dict["brdf"]['calc_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
# 'min': 0.1,'max': 1.0}]]
|
||||
# config_dict["brdf"]['apply_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
# 'min': 0.1,'max': 1.0}]]
|
||||
# config_dict["brdf"]['diagnostic_plots'] = True
|
||||
# config_dict["brdf"]['diagnostic_waves'] = [440,550,660,850]
|
||||
|
||||
#----------------------
|
||||
# ## Flex BRDF configs
|
||||
# ##------------------
|
||||
config_dict["brdf"]['type'] = 'flex'
|
||||
config_dict["brdf"]['grouped'] = True
|
||||
config_dict["brdf"]['geometric'] = 'li_dense_r'
|
||||
config_dict["brdf"]['volume'] = 'ross_thick'
|
||||
config_dict["brdf"]["b/r"] = 2.5
|
||||
config_dict["brdf"]["h/b"] = 2
|
||||
config_dict["brdf"]['sample_perc'] = 0.1
|
||||
config_dict["brdf"]['interp_kind'] = 'linear'
|
||||
config_dict["brdf"]['calc_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.1,'max': 1.0}],
|
||||
['kernel_finite',{}],
|
||||
['ancillary',{'name':'sensor_zn',
|
||||
'min':np.radians(2),'max':'inf' }],
|
||||
['neon_edge',{'radius': 30}],
|
||||
['cloud',{'method':'zhai_2018',
|
||||
'cloud':True,'shadow':True,
|
||||
'T1': 0.01,'t2': 1/10,'t3': 1/4,
|
||||
't4': 1/2,'T7': 9,'T8': 9}]]
|
||||
|
||||
config_dict["brdf"]['apply_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.05,'max': 1.0}]]
|
||||
|
||||
# ## Flex dynamic NDVI params
|
||||
config_dict["brdf"]['bin_type'] = 'dynamic'
|
||||
config_dict["brdf"]['num_bins'] = 18
|
||||
config_dict["brdf"]['ndvi_bin_min'] = 0.05
|
||||
config_dict["brdf"]['ndvi_bin_max'] = 1.0
|
||||
config_dict["brdf"]['ndvi_perc_min'] = 10
|
||||
config_dict["brdf"]['ndvi_perc_max'] = 95
|
||||
|
||||
# ## Flex fixed bins specified by user
|
||||
# config_dict["brdf"]['bin_type'] = 'user'
|
||||
# config_dict["brdf"]['bins'] = [[0.1,.25],[.25,.75],[.75,1]]
|
||||
# ##-----------------
|
||||
|
||||
## Precomputed BRDF coefficients
|
||||
##------------------------------
|
||||
# config_dict["brdf"]['type'] = 'precomputed'
|
||||
# config_dict["brdf"]['coeff_files'] = {}
|
||||
##------------------------------
|
||||
|
||||
#Glint Correction options
|
||||
#################################################################
|
||||
|
||||
'''
|
||||
Types supported:
|
||||
- hochberg
|
||||
- hedley
|
||||
- gao
|
||||
|
||||
Common reference bands include:
|
||||
- 860nm (NIR)
|
||||
- 1650nm (SWIR)
|
||||
- 2190nm (SWIR)
|
||||
|
||||
The Hedley-specific config would be in the form of:
|
||||
[ImagePath]: [y1, y2, x1, x1]
|
||||
|
||||
e.g.:
|
||||
config_dict["glint"]["deep_water_sample"] = {
|
||||
"/path_to_image1": [
|
||||
137, 574, 8034, 8470
|
||||
],
|
||||
"/path_to_image2": [
|
||||
48, 393, 5780, 5925
|
||||
],
|
||||
}
|
||||
'''
|
||||
config_dict["glint"] = {}
|
||||
config_dict['glint']['type'] = 'hedley'
|
||||
config_dict['glint']['correction_wave'] = 1650
|
||||
|
||||
# External masks for glint correction
|
||||
mask_files = glob.glob("/data2/prisma/rfl/PRS_20210629153937_20210629153942_0001_modtran/*_cls")
|
||||
mask_files.sort()
|
||||
file_dict = dict(zip(images,mask_files))
|
||||
config_dict['glint']['apply_mask'] = [["external", {'class' : 1,
|
||||
'files' : file_dict}]]
|
||||
|
||||
config_dict["glint"]["deep_water_sample"] = {
|
||||
images[0]: [
|
||||
225,250,240,260
|
||||
]}
|
||||
|
||||
#Wavelength resampling options
|
||||
##############################
|
||||
'''
|
||||
Types supported:
|
||||
- 'gaussian': needs output waves and output FWHM
|
||||
- 'linear', 'nearest', 'nearest-up',
|
||||
'zero', 'slinear', 'quadratic','cubic': Piecewise
|
||||
interpolation using Scipy interp1d
|
||||
|
||||
config_dict["resampler"] only needed when resampling == True
|
||||
'''
|
||||
config_dict["resample"] = False
|
||||
# config_dict["resampler"] = {}
|
||||
# config_dict["resampler"]['type'] = 'cubic'
|
||||
# config_dict["resampler"]['out_waves'] = []
|
||||
# config_dict["resampler"]['out_fwhm'] = []
|
||||
|
||||
# Remove bad bands from output waves
|
||||
# for wavelength in range(450,660,100):
|
||||
# bad=False
|
||||
# for start,end in config_dict['bad_bands']:
|
||||
# bad = ((wavelength >= start) & (wavelength <=end)) or bad
|
||||
# if not bad:
|
||||
# config_dict["resampler"]['out_waves'].append(wavelength)
|
||||
|
||||
|
||||
config_dict['num_cpus'] = len(images)
|
||||
|
||||
with open(config_file, 'w') as outfile:
|
||||
json.dump(config_dict,outfile,indent=3)
|
||||
338
Flexbrdf/scripts/configs/image_correct_json_generate_gui.py
Normal file
338
Flexbrdf/scripts/configs/image_correct_json_generate_gui.py
Normal file
@ -0,0 +1,338 @@
|
||||
|
||||
# python c:/mydata/image_correct_json_generate_gui.py
|
||||
|
||||
import os
|
||||
import json
|
||||
import glob
|
||||
import numpy as np
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter.filedialog import asksaveasfilename, askdirectory
|
||||
|
||||
|
||||
def fill_config(images, anc_files,out_coef_dir,img_file_type,corr_list, flag_pre_compute=False, topo_coeff = [], brdf_coeff=[]):
|
||||
|
||||
config_dict = {}
|
||||
|
||||
#Only coefficients for good bands will be calculated
|
||||
config_dict['bad_bands'] =[[300,400],[1337,1430],[1800,1960],[2450,2600]]
|
||||
|
||||
config_dict['file_type'] = img_file_type #'envi'
|
||||
aviris_anc_names = ['path_length','sensor_az','sensor_zn',
|
||||
'solar_az', 'solar_zn','phase','slope',
|
||||
'aspect', 'cosine_i','utc_time']
|
||||
#aviris_anc_names = ['sensor_az','sensor_zn',
|
||||
# 'solar_az', 'solar_zn']
|
||||
images.sort()
|
||||
config_dict["input_files"] = images
|
||||
|
||||
if img_file_type=='envi':
|
||||
config_dict["anc_files"] = {}
|
||||
anc_files.sort()
|
||||
for i,image in enumerate(images):
|
||||
config_dict["anc_files"][image] = dict(zip(aviris_anc_names,
|
||||
[[anc_files[i],a] for a in range(len(aviris_anc_names))]))
|
||||
|
||||
config_dict['export'] = {}
|
||||
config_dict["topo"] = {}
|
||||
config_dict["brdf"] = {}
|
||||
|
||||
if flag_pre_compute:
|
||||
config_dict['export']['coeffs'] = False
|
||||
config_dict['export']['image'] = True
|
||||
else:
|
||||
config_dict['export']['coeffs'] = True
|
||||
config_dict['export']['image'] = False
|
||||
|
||||
config_dict['export']['masks'] = False
|
||||
config_dict['export']['subset_waves'] = [660,550,440] #[440,550,660,850] #
|
||||
config_dict['export']['output_dir'] = out_coef_dir
|
||||
print('_'.join(corr_list))
|
||||
|
||||
if len(corr_list)>0:
|
||||
config_dict['export']["suffix"] = '_'.join(corr_list) # 'brdf'
|
||||
else:
|
||||
config_dict['export']["suffix"] = 'raw'
|
||||
|
||||
config_dict["corrections"] = corr_list # ['brdf']
|
||||
|
||||
|
||||
if flag_pre_compute and len(topo_coeff)==len(images):
|
||||
|
||||
config_dict["topo"]['type'] = 'precomputed'
|
||||
topo_files = sorted(topo_coeff)
|
||||
#print(dict(zip(images, topo_files)))
|
||||
config_dict["topo"]['coeff_files'] = dict(zip(images, topo_files))
|
||||
else:
|
||||
config_dict["topo"]['type'] = 'scs+c'
|
||||
|
||||
config_dict["topo"]['calc_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.05,'max': 1.0}]
|
||||
]
|
||||
config_dict["topo"]['apply_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.05,'max': 1.0}]]
|
||||
config_dict["topo"]['c_fit_type'] = 'nnls' #'ols' #'nnls' #
|
||||
|
||||
if flag_pre_compute and len(brdf_coeff)==len(images):
|
||||
|
||||
config_dict["brdf"]['type'] = 'precomputed'
|
||||
brdf_files = sorted(brdf_coeff)
|
||||
config_dict["brdf"]['coeff_files'] = dict(zip(images, brdf_files))
|
||||
else:
|
||||
# Options are 'line','scene', or a float for a custom solar zn
|
||||
# Custom solar zenith angle should be in radians
|
||||
config_dict["brdf"]['solar_zn_type'] ='scene'
|
||||
|
||||
#----------------------
|
||||
# ## Flex BRDF configs
|
||||
# ##------------------
|
||||
config_dict["brdf"]['type'] = 'flex'
|
||||
config_dict["brdf"]['grouped'] = True
|
||||
config_dict["brdf"]['geometric'] = 'li_sparse_r'
|
||||
config_dict["brdf"]['volume'] = 'ross_thick'
|
||||
config_dict["brdf"]["b/r"] = 2.5
|
||||
config_dict["brdf"]["h/b"] = 2
|
||||
config_dict["brdf"]['sample_perc'] = 0.1
|
||||
config_dict["brdf"]['interp_kind'] = 'linear'
|
||||
config_dict["brdf"]['calc_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.05,'max': 1.0}],
|
||||
['kernel_finite',{}],
|
||||
['ancillary',{'name':'sensor_zn',
|
||||
'min':np.radians(2),'max':'inf' }]
|
||||
]
|
||||
|
||||
|
||||
config_dict["brdf"]['apply_mask'] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.05,'max': 1.0}]]
|
||||
|
||||
# ## Flex dynamic NDVI params
|
||||
config_dict["brdf"]['bin_type'] = 'dynamic'
|
||||
config_dict["brdf"]['num_bins'] = 18
|
||||
config_dict["brdf"]['ndvi_bin_min'] = 0.05
|
||||
config_dict["brdf"]['ndvi_bin_max'] = 1.0
|
||||
config_dict["brdf"]['ndvi_perc_min'] = 10
|
||||
config_dict["brdf"]['ndvi_perc_max'] = 95
|
||||
|
||||
|
||||
config_dict["resample"] = False
|
||||
config_dict['num_cpus'] = len(images)
|
||||
|
||||
return config_dict
|
||||
|
||||
'''
|
||||
def update_corr_list(corr_list_):
|
||||
#print(chk_topo.get(),chk_brdf.get())
|
||||
corr_list_ = ['topo']*chk_topo.get()+['brdf']*chk_brdf.get()
|
||||
#print(corr_list)
|
||||
'''
|
||||
|
||||
def gen_config(entry_outdir, entry_outjson,img_list_out, obs_list_out, radio_f_type, corr_list,chk_precompute, topo_list_out,brdf_list_out):
|
||||
|
||||
outdir_name = entry_outdir.get()+'/'
|
||||
out_json = entry_outjson.get()
|
||||
images = img_list_out['text'].split('\n')
|
||||
anc_files = obs_list_out['text'].split('\n')
|
||||
img_file_type = str(radio_f_type.get()).lower()
|
||||
corr_list_str = ['topo']*(corr_list[0].get()) + ['brdf']*(corr_list[1].get())
|
||||
flag_pre_compute = bool(chk_precompute.get())
|
||||
#print(flag_pre_compute,chk_precompute.get())
|
||||
if flag_pre_compute:
|
||||
topo_json_list = topo_list_out['text'].split('\n')
|
||||
brdf_json_list = brdf_list_out['text'].split('\n')
|
||||
|
||||
return_json_dict = fill_config(images, anc_files,outdir_name,img_file_type,corr_list_str,flag_pre_compute=flag_pre_compute, topo_coeff = topo_json_list, brdf_coeff=brdf_json_list)
|
||||
else:
|
||||
|
||||
return_json_dict = fill_config(images, anc_files,outdir_name,img_file_type,corr_list_str)
|
||||
|
||||
with open(out_json, 'w') as outfile:
|
||||
json.dump(return_json_dict,outfile,indent=3)
|
||||
window.title(f"File saved- {out_json}")
|
||||
|
||||
def save_file(txt_out_json):
|
||||
"""Save the current file as a new file."""
|
||||
filepath = asksaveasfilename(
|
||||
defaultextension=".json",
|
||||
filetypes=[("JSON Files", "*.json"), ("All Files", "*.*")],
|
||||
)
|
||||
|
||||
if not filepath:
|
||||
return
|
||||
|
||||
txt_out_json.delete(0,tk.END)
|
||||
txt_out_json.insert(0,filepath)
|
||||
|
||||
window.title(f"Export Configuration JSON - {filepath}")
|
||||
|
||||
def open_folder(out_component):
|
||||
"""Open a file for editing."""
|
||||
in_img_dir = askdirectory()
|
||||
if not in_img_dir:
|
||||
return
|
||||
|
||||
#print(in_img_dir)
|
||||
out_component.delete(0, tk.END)
|
||||
out_component.insert(0,in_img_dir)
|
||||
|
||||
|
||||
window.title(f"Folder- {in_img_dir}")
|
||||
|
||||
def open_file(out_component, list_component, radio_f_type=None, pattern=None):
|
||||
"""Open a file for editing."""
|
||||
in_img_dir = askdirectory()
|
||||
if not in_img_dir:
|
||||
return
|
||||
|
||||
#out_component.delete("1.0", tk.END)
|
||||
#out_component.insert("1.0",in_img_dir)
|
||||
out_component["text"] = in_img_dir
|
||||
if pattern is None:
|
||||
img_file_type = str(radio_f_type.get()).lower()
|
||||
file_ext_list = {'envi':'*img','neon':'*.h5'}
|
||||
pattern = file_ext_list[img_file_type]
|
||||
|
||||
|
||||
#if pattern is None:
|
||||
# return in_img_dir
|
||||
|
||||
file_list = sorted(glob.glob(in_img_dir+'/'+pattern))
|
||||
|
||||
if len(file_list)==0:
|
||||
list_component['text']= 'No files selected'
|
||||
return
|
||||
|
||||
list_component['text']= '\n'.join([ os.path.normpath(x) for x in file_list])
|
||||
#print(list_component['text'])
|
||||
|
||||
window.title(f"Folder- {in_img_dir}")
|
||||
|
||||
window = tk.Tk()
|
||||
window.title("Setup image correction configuration file")
|
||||
|
||||
#window.rowconfigure(0, minsize=400, weight=1)
|
||||
#window.columnconfigure(1, minsize=600, weight=1)
|
||||
|
||||
|
||||
#txt_edit = tk.Text(window)
|
||||
|
||||
frm_img_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
|
||||
frm_img_buttons.columnconfigure(1, minsize=300, weight=1)
|
||||
frm_img_buttons.rowconfigure(1, minsize=50, weight=1)
|
||||
|
||||
frm_obs_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
|
||||
frm_obs_buttons.columnconfigure(1, minsize=300, weight=1)
|
||||
frm_obs_buttons.rowconfigure(1, minsize=50, weight=1)
|
||||
|
||||
frm_out_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
|
||||
frm_out_buttons.columnconfigure(1, weight=1) #, minsize=300
|
||||
|
||||
frm_out_json_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
|
||||
frm_out_json_buttons.columnconfigure(1, weight=1) #minsize=300,
|
||||
|
||||
frm_file_type = tk.Frame(window, relief=tk.RAISED, bd=2)
|
||||
frm_corr_type = tk.Frame(window, relief=tk.RAISED, bd=2)
|
||||
|
||||
frm_precomp = tk.Frame(window, relief=tk.RAISED, bd=2,highlightbackground="grey",highlightthickness=5,padx=5, pady=5)
|
||||
frm_precomp.columnconfigure(1,weight=1)
|
||||
frm_precomp.rowconfigure(1, minsize=50, weight=1)
|
||||
frm_pre_topo_buttons = tk.Frame(frm_precomp, relief=tk.RAISED, bd=2)
|
||||
frm_pre_topo_buttons.columnconfigure(1, minsize=280, weight=1)
|
||||
#frm_pre_topo_buttons.rowconfigure(1, minsize=50, weight=1)
|
||||
|
||||
frm_pre_brdf_buttons = tk.Frame(frm_precomp, relief=tk.RAISED, bd=2)
|
||||
frm_pre_brdf_buttons.columnconfigure(1, minsize=280, weight=1)
|
||||
#frm_pre_brdf_buttons.rowconfigure(1, minsize=50, weight=1)
|
||||
|
||||
frm_final_gen = tk.Frame(window, relief=tk.RAISED, bd=2,highlightbackground="grey",highlightthickness=5)
|
||||
frm_final_gen.rowconfigure(0, minsize=50, weight=0)
|
||||
frm_final_gen.columnconfigure(0, minsize=100, weight=1) #
|
||||
frm_final_gen.columnconfigure(1, minsize=50, weight=0)
|
||||
frm_final_gen.columnconfigure(2, minsize=100, weight=1)
|
||||
|
||||
label_img_dir = tk.Label(frm_img_buttons,text="image", fg="white", bg="black")
|
||||
label_obs_dir = tk.Label(frm_obs_buttons,text="image", fg="white", bg="black")
|
||||
txt_outdir = tk.Entry(frm_out_buttons)
|
||||
|
||||
img_list_out = tk.Label(frm_img_buttons,bg="grey",anchor="w")
|
||||
obs_list_out = tk.Label(frm_obs_buttons,bg="grey",anchor="w")
|
||||
|
||||
|
||||
btn_open1 = tk.Button(frm_img_buttons, text="Image Folder...", command=lambda: open_file(label_img_dir,img_list_out,radio_f_type=f_type) ) #'*img'
|
||||
btn_open2 = tk.Button(frm_obs_buttons, text="Obs_ort Folder...", command=lambda: open_file(label_obs_dir,obs_list_out,pattern='*obs_ort'))
|
||||
btn_open3 = tk.Button(frm_out_buttons, text="Output coeff Folder...", command=lambda: open_folder(txt_outdir)) #, command=open_file(txt_edit, None)
|
||||
#btn_open1 = tk.Button(frm_img_buttons, text="Image Folder...", command=lambda: open_file(label_img_dir,img_list_out,radio_f_type=f_type) ) #'*img'
|
||||
#btn_open2 = tk.Button(frm_obs_buttons, text="Obs_ort Folder...", command=lambda: open_file(label_obs_dir,obs_list_out,pattern='*obs_ort'))
|
||||
|
||||
btn_open_topo = tk.Button(frm_pre_topo_buttons, text="TOPO json Folder...", command=lambda: open_file(label_pre_topo_dir,topo_list_out,pattern='*topo_coeffs*.json'))
|
||||
btn_open_brdf = tk.Button(frm_pre_brdf_buttons, text="BRDF json Folder...", command=lambda: open_file(label_pre_brdf_dir,brdf_list_out,pattern='*brdf_coeffs*.json'))
|
||||
|
||||
txt_out_json = tk.Entry(frm_out_json_buttons)
|
||||
|
||||
btn_save = tk.Button(frm_out_json_buttons, text="Save As...", command=lambda: save_file(txt_out_json))
|
||||
|
||||
btn_open1.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
|
||||
label_img_dir.grid(row=0, column=1, sticky="ew", padx=5, pady=5)
|
||||
img_list_out.grid(row=1, columnspan=2, sticky="nsew", padx=5, pady=5)
|
||||
|
||||
btn_open2.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
|
||||
label_obs_dir.grid(row=0, column=1, sticky="ew", padx=5, pady=5)
|
||||
obs_list_out.grid(row=1, columnspan=2, sticky="nsew", padx=5, pady=5)
|
||||
|
||||
btn_open3.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
|
||||
txt_outdir.grid(row=0, column=1, sticky="ew", padx=5, pady=5)
|
||||
btn_save.grid(row=0, column=0, sticky="ew", padx=5)
|
||||
txt_out_json.grid(row=0, column=1, sticky="ew", padx=5, pady=5)
|
||||
|
||||
f_type = tk.StringVar(value="envi")
|
||||
ev_btn = tk.Radiobutton(frm_file_type, text='ENVI (*img)', variable=f_type, value='envi')
|
||||
h5_btn = tk.Radiobutton(frm_file_type, text='NEON HDF5 (*.h5)', variable=f_type, value='neon')
|
||||
ev_btn.grid(row=0, column=0, sticky="ew", padx=5)
|
||||
h5_btn.grid(row=0, column=1, sticky="ew", padx=5)
|
||||
|
||||
chk_topo = tk.IntVar(value=0)
|
||||
chk_brdf = tk.IntVar(value=1)
|
||||
|
||||
chk_topo_btn = tk.Checkbutton(frm_corr_type, text='TOPO', variable=chk_topo, onvalue=1, offvalue=0) #, command=lambda: update_corr_list(corr_list))
|
||||
chk_brdf_btn = tk.Checkbutton(frm_corr_type, text='BRDF', variable=chk_brdf, onvalue=1, offvalue=0) #, command=lambda: update_corr_list(corr_list))
|
||||
chk_topo_btn.grid(row=0, column=0, sticky="ew", padx=5)
|
||||
chk_brdf_btn.grid(row=0, column=1, sticky="ew", padx=5)
|
||||
corr_list = [chk_topo,chk_brdf]
|
||||
|
||||
chk_precompute = tk.IntVar(value=0)
|
||||
coeff_list= []
|
||||
label_precomput = tk.Checkbutton(frm_precomp, text='Load Precomputed Coefficients', variable=chk_precompute, onvalue=1, offvalue=0,anchor="center") #tk.Label(frm_precomp,text="Precomputed Coefficients")
|
||||
label_precomput.grid(row=0, columnspan=2, sticky="ew", padx=2, pady=2)
|
||||
btn_open_topo.grid(row=0, column=0, sticky="ew", padx=2, pady=2)
|
||||
btn_open_brdf.grid(row=0, column=0, sticky="ew", padx=2, pady=2)
|
||||
label_pre_topo_dir = tk.Label(frm_pre_topo_buttons,text="topo json", fg="white", bg="black")
|
||||
label_pre_topo_dir.grid(row=0, column=1, sticky="ew", padx=2, pady=2)
|
||||
label_pre_brdf_dir = tk.Label(frm_pre_brdf_buttons,text="brdf json", fg="white", bg="black")
|
||||
label_pre_brdf_dir.grid(row=0, column=1, sticky="ew", padx=2, pady=2)
|
||||
topo_list_out = tk.Label(frm_pre_topo_buttons,bg="grey",anchor="w")
|
||||
topo_list_out.grid(row=1, columnspan=2, sticky="ew", padx=2,pady=2)
|
||||
brdf_list_out = tk.Label(frm_pre_brdf_buttons,bg="grey",anchor="w")
|
||||
brdf_list_out.grid(row=1, columnspan=2, sticky="ew", padx=2,pady=2)
|
||||
frm_pre_topo_buttons.grid(row=1, column=0, sticky="ew")
|
||||
frm_pre_brdf_buttons.grid(row=1, column=1, sticky="ew")
|
||||
|
||||
|
||||
#img_list_out = tk.Label(frm_img_buttons,bg="grey",anchor="w")
|
||||
#obs_list_out = tk.Label(frm_obs_buttons,bg="grey",anchor="w")
|
||||
|
||||
|
||||
|
||||
btn_gen = tk.Button(frm_final_gen, text="Generate", font=("Calibri",12,"bold"), command=lambda: gen_config(txt_outdir,txt_out_json,img_list_out, obs_list_out,f_type,corr_list,chk_precompute,topo_list_out, brdf_list_out))
|
||||
#btn_gen.place(relx=.5, rely=.5,anchor= 'e')
|
||||
btn_gen.grid(row=0,column=1,sticky="wens") #anchor='center',
|
||||
#btn_gen.place(relx=0.5, rely=0.95, anchor=tk.CENTER)
|
||||
|
||||
frm_img_buttons.grid(row=0, column=0, sticky="ew")
|
||||
frm_obs_buttons.grid(row=0, column=1, sticky="ew")
|
||||
frm_out_buttons.grid(row=1, columnspan=2, sticky="we")
|
||||
frm_file_type.grid(row=2,column=0, sticky="ew")
|
||||
frm_corr_type.grid(row=2,column=1, sticky="ew")
|
||||
frm_precomp.grid(row=3,columnspan=2, sticky="nsew")
|
||||
frm_out_json_buttons.grid(row=4, columnspan=2, sticky="ew")
|
||||
frm_final_gen.grid(row=6, columnspan=2, sticky="nsew") #, sticky="nsew"
|
||||
|
||||
window.mainloop()
|
||||
117
Flexbrdf/scripts/configs/plsr_model_format_v0_1.py
Normal file
117
Flexbrdf/scripts/configs/plsr_model_format_v0_1.py
Normal file
@ -0,0 +1,117 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
HyTools: Hyperspectral image processing library
|
||||
|
||||
Copyright (C) 2021 University of Wisconsin
|
||||
|
||||
Authors: Adam Chlus, Zhiwei Ye, Philip Townsend.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, version 3 of the License.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
JSON format for PLSR trait models v0.1
|
||||
|
||||
This version assumes that all transforms are applied using all model wavelengths.
|
||||
|
||||
TODO: Develop standard codes for spectrometer, both airborne/spaceborne and field.
|
||||
TODO: Allow for more options for specifying wavelength subsets
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
|
||||
model_dict = {}
|
||||
|
||||
# Metadata
|
||||
#####################################
|
||||
'''
|
||||
trait : Trait name (str)
|
||||
units : Trait units (str)
|
||||
description: Model description (str)
|
||||
wavelength_units: Wavelength units (str)
|
||||
wavelengths : Model wavelengths (list)
|
||||
Only wavelengths used in the model should be
|
||||
included in the list of wavelengths.
|
||||
fwhm : Model fwhm (list)
|
||||
type : Model type (str)
|
||||
'''
|
||||
model_dict["name"] = ''
|
||||
model_dict["units"] = ''
|
||||
model_dict["description"] = ''
|
||||
model_dict["wavelength_units"] = ''
|
||||
model_dict["wavelengths"] = []
|
||||
model_dict["fwhm"] = []
|
||||
model_dict["spectrometer"] = ''
|
||||
model_dict["type"] = ''
|
||||
|
||||
# Diagnostics
|
||||
#####################################
|
||||
'''Currently the only required diagnostics are 'min'
|
||||
and 'max', these are the min and max values of the
|
||||
dataset used to build the model and are used to generate
|
||||
the data range mask, which identifies pixels with predictions
|
||||
outside of the model dataset range.
|
||||
|
||||
'''
|
||||
model_dict["model_diagnostics"] = {}
|
||||
model_dict["model_diagnostics"]["rmse"] = 0.0
|
||||
model_dict["model_diagnostics"]["r_squared"] = 0.0
|
||||
model_dict["model_diagnostics"]["min"] = 0.0
|
||||
model_dict["model_diagnostics"]["max"] = 0.0
|
||||
|
||||
# Model
|
||||
#####################################
|
||||
'''
|
||||
transform: List of transforms to be applied in order of application.
|
||||
Options:
|
||||
- 'vector': vector norm using np.linalg.norm
|
||||
- 'mean' : Normalize to mean
|
||||
- 'absorb' : log(1/R)
|
||||
Examples:
|
||||
['vector','absorb']
|
||||
Empty list for no transforms ([])
|
||||
coefficients: List of lists, sublists are the coefficients for
|
||||
model iterations.
|
||||
|
||||
intercepts : Permuted model intercepts (list)
|
||||
components : Number of model component (int)
|
||||
'''
|
||||
|
||||
model_dict['model'] = {}
|
||||
model_dict['model']["components"] = 0
|
||||
model_dict['model']["transform"] = ['mean']
|
||||
model_dict['model']["intercepts"] = []
|
||||
model_dict['model']["coefficients"] =[[],[]]
|
||||
|
||||
model_path = '*.json'
|
||||
with open(model_path, 'w') as outfile:
|
||||
json.dump(model_dict,outfile)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
99
Flexbrdf/scripts/configs/trait_estimate_json_generate.py
Normal file
99
Flexbrdf/scripts/configs/trait_estimate_json_generate.py
Normal file
@ -0,0 +1,99 @@
|
||||
'''Template script for generating trait_estimate configuration JSON files.
|
||||
'''
|
||||
|
||||
import os
|
||||
import json
|
||||
import glob
|
||||
|
||||
home = os.path.expanduser("~")
|
||||
|
||||
#Output path for configuration file
|
||||
config_file = "/.json"
|
||||
|
||||
config_dict = {}
|
||||
config_dict['file_type'] = 'envi'
|
||||
config_dict["output_dir"] = './'
|
||||
config_dict['bad_bands'] =[[300,400],[1337,1430],[1800,1960],[2450,2600]]
|
||||
|
||||
# Input data settings for NEON
|
||||
#################################################################
|
||||
# config_dict['file_type'] = 'neon'
|
||||
# images= glob.glob("*.h5")
|
||||
# images.sort()
|
||||
# config_dict["input_files"] = images
|
||||
|
||||
# Input data settings for ENVI
|
||||
#################################################################
|
||||
''' Only difference between ENVI and NEON settings is the specification
|
||||
of the ancillary datasets (ex. viewing and solar geometry). All hytools
|
||||
functions assume that the ancillary data and the image date are the same
|
||||
size, spatially, and are ENVI formatted files.
|
||||
|
||||
The ancillary parameter is a dictionary with a key per image. Each value
|
||||
per image is also a dictionary where the key is the dataset name and the
|
||||
value is list consisting of the file path and the band number.
|
||||
'''
|
||||
|
||||
config_dict['file_type'] = 'envi'
|
||||
aviris_anc_names = ['path_length','sensor_az','sensor_zn',
|
||||
'solar_az', 'solar_zn','phase','slope',
|
||||
'aspect', 'cosine_i','utc_time']
|
||||
images= glob.glob("*img")
|
||||
images.sort()
|
||||
config_dict["input_files"] = images
|
||||
|
||||
config_dict["anc_files"] = {}
|
||||
anc_files = glob.glob("*ort")
|
||||
anc_files.sort()
|
||||
for i,image in enumerate(images):
|
||||
config_dict["anc_files"][image] = dict(zip(aviris_anc_names,
|
||||
[[anc_files[i],a] for a in range(len(aviris_anc_names))]))
|
||||
|
||||
config_dict['num_cpus'] = len(images)
|
||||
|
||||
# Assign correction coefficients
|
||||
##########################################################
|
||||
''' Specify correction(s) to apply and paths to coefficients.
|
||||
'''
|
||||
|
||||
config_dict['corrections'] = ['topo','brdf']
|
||||
|
||||
topo_files = glob.glob("*topo.json")
|
||||
topo_files.sort()
|
||||
config_dict["topo"] = dict(zip(images,topo_files))
|
||||
|
||||
brdf_files = glob.glob("*brdf.json")
|
||||
brdf_files.sort()
|
||||
config_dict["brdf"] = dict(zip(images,brdf_files))
|
||||
|
||||
# Select wavelength resampling type
|
||||
##########################################################
|
||||
'''Wavelength resampler will only be used if image wavelengths
|
||||
and model wavelengths do not match exactly
|
||||
|
||||
See image_correct_json_generate.py for options.
|
||||
|
||||
'''
|
||||
config_dict["resampling"] = {}
|
||||
config_dict["resampling"]['type'] = 'cubic'
|
||||
|
||||
# Masks
|
||||
##########################################################
|
||||
'''Specify list of masking layers to be appended to the
|
||||
trait map. Each will be placed in a separate layer.
|
||||
|
||||
For no masks provide an empty list: []
|
||||
'''
|
||||
config_dict["masks"] = [["ndi", {'band_1': 850,'band_2': 660,
|
||||
'min': 0.1,'max': 1.0}],
|
||||
['neon_edge',{'radius': 30}]]
|
||||
|
||||
# Define trait coefficients
|
||||
##########################################################
|
||||
models = glob.glob('*.json')
|
||||
models.sort()
|
||||
config_dict["trait_models"] = models
|
||||
|
||||
with open(config_file, 'w') as outfile:
|
||||
json.dump(config_dict,outfile)
|
||||
|
||||
Reference in New Issue
Block a user