Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/workflows/build_and_test_app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: ALCD

on:
pull_request:
branches:
- "master"

permissions:
contents: read
env:
OTB_RELEASE: 9.1.0
jobs:
quality:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: setup python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: install quality deps
run: |
pip install pylint mccabe
- name: code quality
run: |
pylint --disable=all --fail-under=10 --enable=too-many-statements --max-statements=100 .
pylint --disable=all --fail-under=10 --enable=too-many-nested-blocks .
./continuous_integration/scripts/check_mccabe_complexity.sh 25 .
test:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: setup python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
sudo apt install -y --no-install-recommends g++ swig cmake make
pip install "numpy<2"
curl https://www.orfeo-toolbox.org/packages/archives/OTB/OTB-$OTB_RELEASE-Linux.tar.gz -o OTB-$OTB_RELEASE-Linux.tar.gz
tar xvf OTB-$OTB_RELEASE-Linux.tar.gz --one-top-level="/opt/otb"
source /opt/otb/otbenv.profile
sh /opt/otb/recompile_bindings.sh
python -m pip install --upgrade pip
pip install pytest pytest-cov
if [ -f docker/requirements.txt ]; then pip install -r docker/requirements.txt; fi
- name: pytest
run: |
cd tests
export CMAKE_PREFIX_PATH=/opt/otb
export PYTHONPATH=/opt/otb/lib/python3/dist-packages:/opt/otb/lib/otb/python
export GDAL_DRIVER_PATH=disable
export GDAL_DATA=/opt/otb/share/gdal
export PROJ_LIB=/opt/otb/share/proj
export PATH=/opt/otb/bin:$PATH
export LD_LIBRARY_PATH=/opt/otb/lib:$LD_LIBRARY_PATH
export OTB_APPLICATION_PATH=/opt/otb/lib/otb/applications
export OTB_INSTALL_DIR=/opt/otb
export LC_NUMERIC=C

pytest -s --cov-fail-under=65
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.pyc
*.py~
.gitignore~
*.sh~
*.json~
25 changes: 13 additions & 12 deletions L1C_band_composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def create_specific_indices(in_bands_dir, out_tif, indice_name, resolution=60):
print('Please enter a valid indice name')


def create_time_difference_band(global_parameters, band_num, out_tif, resolution=60):
def create_time_difference_band(global_parameters, paths_parameters, band_num, out_tif, resolution=60):
'''
Create a TIF being the difference between the cloudy date and the clear date
The band_num is the number of the band of interest
Expand All @@ -125,9 +125,9 @@ def create_time_difference_band(global_parameters, band_num, out_tif, resolution
clear_date = global_parameters["user_choices"]["clear_date"]

current_dir, current_band_prefix, current_date = find_directory_names.get_L1C_dir(
location, current_date, display=False)
location, current_date,paths_parameters, display=False)
clear_dir, clear_band_prefix, clear_date = find_directory_names.get_L1C_dir(
location, clear_date, display=False)
location, clear_date,paths_parameters, display=False)

band_num_str = '{:02d}'.format(band_num)

Expand Down Expand Up @@ -260,7 +260,7 @@ def dtm_addition(location, out_band, resolution=60):
Create the adapted Digital Terrain Model
From the original one, change its resolution
'''
paths_configuration = json.load(open(op.join('..', 'paths_configuration.json')))
paths_configuration = json.load(open(op.join('parameters_files', 'paths_configuration.json')))
tile = paths_configuration["tile_location"][location]

original_DTM_dir = paths_configuration["global_chains_paths"]["DTM_input"]
Expand Down Expand Up @@ -293,7 +293,7 @@ def resize_band(in_band, out_band, pixelresX, pixelresY):
os.system(build_warp)


def create_image_compositions(global_parameters, location, current_date, heavy=False, force=False):
def create_image_compositions(global_parameters, location, paths_parameters, current_date, heavy=False, force=False):
#
potential_final_tif = op.join(global_parameters["user_choices"]["main_dir"],
'In_data', 'Image', global_parameters["user_choices"]["raw_img"])
Expand All @@ -304,7 +304,7 @@ def create_image_compositions(global_parameters, location, current_date, heavy=F

# get the directory of the bands
bands_dir, band_prefix, date = find_directory_names.get_L1C_dir(
location, current_date, display=True)
location, current_date, paths_parameters, display=True)
# --------------------------------------------
# ------ Low resolution TIF with all the bands
# Preparation
Expand Down Expand Up @@ -356,7 +356,7 @@ def create_image_compositions(global_parameters, location, current_date, heavy=F
out_dir_bands = op.join(global_parameters["user_choices"]["main_dir"], 'Intermediate')
for band_num in bands_num:
out_tif = op.join(out_dir_bands, ('time_' + str(band_num) + '.tif'))
create_time_difference_band(global_parameters, band_num, out_tif, resolution=resolution)
create_time_difference_band(global_parameters, paths_parameters, band_num, out_tif, resolution=resolution)
additional_bands.append(str(out_tif))

# --- Create the main TIF with low resolution
Expand Down Expand Up @@ -429,7 +429,7 @@ def create_image_compositions(global_parameters, location, current_date, heavy=F
return


def create_no_data_tif(global_parameters, out_tif, dilation_radius=10):
def create_no_data_tif(global_parameters, paths_parameters, out_tif, dilation_radius=10):
'''
Create the no_data TIF using both the clear and cloudy date.
Used in the 'layers_creation.create_no_data_shp'
Expand All @@ -439,9 +439,9 @@ def create_no_data_tif(global_parameters, out_tif, dilation_radius=10):
clear_date = global_parameters["user_choices"]["clear_date"]

current_dir, current_band_prefix, current_date = find_directory_names.get_L1C_dir(
location, current_date, display=False)
location, current_date, paths_parameters, display=False)
clear_dir, clear_band_prefix, clear_date = find_directory_names.get_L1C_dir(
location, clear_date, display=False)
location, clear_date, paths_parameters, display=False)

# Band number, the 1 is 20m resolution, change it if
# other resolution is wanted
Expand All @@ -462,8 +462,9 @@ def create_no_data_tif(global_parameters, out_tif, dilation_radius=10):
Dilatation.SetParameterInputImage("in", BandMathX.GetParameterOutputImage("out"))
Dilatation.SetParameterString("out", str(out_tif))
Dilatation.SetParameterString("filter", "dilate")
Dilatation.SetParameterInt("structype.ball.xradius", dilation_radius)
Dilatation.SetParameterInt("structype.ball.yradius", dilation_radius)
Dilatation.SetParameterString("structype", "ball")
Dilatation.SetParameterInt("xradius", dilation_radius)
Dilatation.SetParameterInt("yradius", dilation_radius)
Dilatation.UpdateParameters()
Dilatation.ExecuteAndWriteOutput()

Expand Down
24 changes: 10 additions & 14 deletions OTB_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def compute_image_stats(global_parameters, proceed=True):
print(" Compute Images Statistics")
ComputeImagesStatistics = otbApplication.Registry.CreateApplication("ComputeImagesStatistics")
ComputeImagesStatistics.SetParameterStringList("il", [str(raw_img)])
ComputeImagesStatistics.SetParameterString("out", str(img_stats))
ComputeImagesStatistics.SetParameterString("out.xml", str(img_stats))
ComputeImagesStatistics.ExecuteAndWriteOutput()

print('Done')
Expand All @@ -85,7 +85,7 @@ def compute_samples_stats(global_parameters, proceed=True):
'''
1. Compute the samples stats
'''
print " Polygon Classes Statistics"
print( " Polygon Classes Statistics")

main_dir = global_parameters["user_choices"]["main_dir"]
raw_img = op.join(main_dir, 'In_data', 'Image', global_parameters["user_choices"]["raw_img"])
Expand All @@ -98,7 +98,7 @@ def compute_samples_stats(global_parameters, proceed=True):
global_parameters["general"]["no_data_mask"])
no_data_mask = no_data_shp[0:-4] + '.tif'

PolygonClassStatistics = otbApplication.Registry_CreateApplication("PolygonClassStatistics")
PolygonClassStatistics = otbApplication.Registry.CreateApplication("PolygonClassStatistics")
PolygonClassStatistics.SetParameterString("in", str(raw_img))
PolygonClassStatistics.SetParameterString("vec", str(training_shp))
PolygonClassStatistics.SetParameterString("out", str(class_stats))
Expand Down Expand Up @@ -167,7 +167,7 @@ def select_samples(global_parameters, strategy="smallest", proceed=True):
no_data_mask = no_data_shp[0:-4] + '.tif'

print(" Training Samples Selection")
SampleSelection = otbApplication.Registry_CreateApplication("SampleSelection")
SampleSelection = otbApplication.Registry.CreateApplication("SampleSelection")
SampleSelection.SetParameterString("in", str(raw_img))
SampleSelection.SetParameterString("vec", str(training_shp))
SampleSelection.SetParameterString("mask", str(no_data_mask))
Expand Down Expand Up @@ -207,7 +207,7 @@ def extract_samples(global_parameters, proceed=True):
main_dir, 'Samples', global_parameters["general"]["training_samples_location"])

print(" Training Samples Extraction")
SampleExtraction = otbApplication.Registry_CreateApplication("SampleExtraction")
SampleExtraction = otbApplication.Registry.CreateApplication("SampleExtraction")
SampleExtraction.SetParameterString("in", str(raw_img))
SampleExtraction.SetParameterString("vec", str(training_samples_location))
SampleExtraction.SetParameterString("outfield", "prefix")
Expand All @@ -223,12 +223,11 @@ def extract_samples(global_parameters, proceed=True):
# -------- 2. MODEL TRAINING ---------------------


def train_model(global_parameters, shell=True, proceed=True):
def train_model(global_parameters, model_parameters, shell=True, proceed=True):
'''
5. Train the model
'''
main_dir = global_parameters["user_choices"]["main_dir"]

method = global_parameters["classification"]["method"]
training_samples_extracted = op.join(
main_dir, 'Samples', global_parameters["general"]["training_samples_extracted"])
Expand All @@ -249,16 +248,13 @@ def train_model(global_parameters, shell=True, proceed=True):

if proceed == True:
print(" Train Vector Classifier")
# load the model parameters
with open(op.join('parameters_files', 'model_parameters.json'), 'r') as file_model:
dico = json.load(file_model)
if shell == True:
# can be run through the API or through the shell
command = 'otbcli_TrainVectorClassifier -io.vd {} -cfield {} -io.out {} -classifier {} -feat {}'.format(
training_samples_extracted, "class", model_out, method, str(features))

model_options = ''
for key, value in dico[method].iteritems():
for key, value in model_parameters[method].items():
model_options = model_options + ' -classifier.{}.{} {}'.format(method, key, value)

command = command + model_options
Expand All @@ -274,7 +270,7 @@ def train_model(global_parameters, shell=True, proceed=True):
TrainVectorClassifier.SetParameterStringList("feat", features_API)
TrainVectorClassifier.SetParameterString("classifier", str(method))

for key, value in dico[method].iteritems():
for key, value in model_parameters[method].items():
TrainVectorClassifier.SetParameterString(
str("classifier.{}.{}".format(method, key)), str(value))

Expand Down Expand Up @@ -356,7 +352,7 @@ def fancy_classif_viz(global_parameters, proceed=True):
main_dir = global_parameters["user_choices"]["main_dir"]

img_labeled = op.join(main_dir, 'Out', global_parameters["general"]["img_labeled_regularized"])
color_table = op.join('color_tables', global_parameters["color_tables"]["otb"])
color_table = global_parameters["color_tables"]["otb"]
out_image_colorized = op.join(main_dir, 'Out', 'colorized_classif.png')

ColorMapping = otbApplication.Registry.CreateApplication("ColorMapping")
Expand Down Expand Up @@ -396,7 +392,7 @@ def compute_mat_conf(global_parameters, show=True, proceed=True):

print('Done')

with open(conf_matrix, 'rb') as csvfile:
with open(conf_matrix, 'r') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
rows = []
for row in reader:
Expand Down
Loading