Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
iamap
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
AMAP
iamap
Commits
74284be8
Commit
74284be8
authored
7 months ago
by
paul.tresson_ird.fr
Browse files
Options
Downloads
Patches
Plain Diff
reorganize plugin structure
parent
5b3e5cbe
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/iamap/iamap.py
+0
-234
0 additions, 234 deletions
src/iamap/iamap.py
src/iamap/provider.py
+0
-46
0 additions, 46 deletions
src/iamap/provider.py
src/iamap/utils/geo.py
+0
-118
0 additions, 118 deletions
src/iamap/utils/geo.py
with
0 additions
and
398 deletions
src/iamap/iamap.py
deleted
100644 → 0
+
0
−
234
View file @
5b3e5cbe
import
processing
from
PyQt5.QtWidgets
import
(
QAction
,
QToolBar
,
QApplication
,
QDialog
)
from
PyQt5.QtCore
import
pyqtSignal
,
QObject
from
qgis.core
import
QgsApplication
from
qgis.gui
import
QgisInterface
from
.provider
import
IAMapProvider
from
.icons
import
QIcon_EncoderTool
,
QIcon_ReductionTool
,
QIcon_ClusterTool
,
QIcon_SimilarityTool
,
QIcon_RandomforestTool
class
IAMap
(
QObject
):
execute_iamap
=
pyqtSignal
()
def
__init__
(
self
,
iface
:
QgisInterface
,
cwd
:
str
):
super
().
__init__
()
self
.
iface
=
iface
self
.
cwd
=
cwd
def
initProcessing
(
self
):
self
.
provider
=
IAMapProvider
()
QgsApplication
.
processingRegistry
().
addProvider
(
self
.
provider
)
def
initGui
(
self
):
self
.
initProcessing
()
self
.
toolbar
:
QToolBar
=
self
.
iface
.
addToolBar
(
'
IAMap Toolbar
'
)
self
.
toolbar
.
setObjectName
(
'
IAMapToolbar
'
)
self
.
toolbar
.
setToolTip
(
'
IAMap Toolbar
'
)
self
.
actionEncoder
=
QAction
(
QIcon_EncoderTool
,
"
Deep Learning Image Encoder
"
,
self
.
iface
.
mainWindow
()
)
self
.
actionReducer
=
QAction
(
QIcon_ReductionTool
,
"
Reduce dimensions
"
,
self
.
iface
.
mainWindow
()
)
self
.
actionCluster
=
QAction
(
QIcon_ClusterTool
,
"
Cluster raster
"
,
self
.
iface
.
mainWindow
()
)
self
.
actionSimilarity
=
QAction
(
QIcon_SimilarityTool
,
"
Compute similarity
"
,
self
.
iface
.
mainWindow
()
)
self
.
actionRF
=
QAction
(
QIcon_RandomforestTool
,
"
Use Random Forest algorithm
"
,
self
.
iface
.
mainWindow
()
)
self
.
actionEncoder
.
setObjectName
(
"
mActionEncoder
"
)
self
.
actionReducer
.
setObjectName
(
"
mActionReducer
"
)
self
.
actionCluster
.
setObjectName
(
"
mActionCluster
"
)
self
.
actionSimilarity
.
setObjectName
(
"
mactionSimilarity
"
)
self
.
actionRF
.
setObjectName
(
"
mactionRF
"
)
self
.
actionEncoder
.
setToolTip
(
"
Encode a raster with a deep learning backbone
"
)
self
.
actionReducer
.
setToolTip
(
"
Reduce raster dimensions
"
)
self
.
actionCluster
.
setToolTip
(
"
Cluster raster
"
)
self
.
actionSimilarity
.
setToolTip
(
"
Compute similarity
"
)
self
.
actionRF
.
setToolTip
(
"
Use Random Forest
"
)
self
.
actionEncoder
.
triggered
.
connect
(
self
.
encodeImage
)
self
.
actionReducer
.
triggered
.
connect
(
self
.
reduceImage
)
self
.
actionCluster
.
triggered
.
connect
(
self
.
clusterImage
)
self
.
actionSimilarity
.
triggered
.
connect
(
self
.
similarityImage
)
self
.
actionRF
.
triggered
.
connect
(
self
.
rfImage
)
self
.
toolbar
.
addAction
(
self
.
actionEncoder
)
self
.
toolbar
.
addAction
(
self
.
actionReducer
)
self
.
toolbar
.
addAction
(
self
.
actionCluster
)
self
.
toolbar
.
addAction
(
self
.
actionSimilarity
)
self
.
toolbar
.
addAction
(
self
.
actionRF
)
def
unload
(
self
):
# self.wdg_select.setVisible(False)
self
.
iface
.
removeToolBarIcon
(
self
.
actionEncoder
)
self
.
iface
.
removeToolBarIcon
(
self
.
actionReducer
)
self
.
iface
.
removeToolBarIcon
(
self
.
actionCluster
)
self
.
iface
.
removeToolBarIcon
(
self
.
actionSimilarity
)
self
.
iface
.
removeToolBarIcon
(
self
.
actionRF
)
del
self
.
actionEncoder
del
self
.
actionReducer
del
self
.
actionCluster
del
self
.
actionSimilarity
del
self
.
actionRF
del
self
.
toolbar
QgsApplication
.
processingRegistry
().
removeProvider
(
self
.
provider
)
def
encodeImage
(
self
):
'''
'''
result
=
processing
.
execAlgorithmDialog
(
'
iamap:encoder
'
,
{})
print
(
result
)
# Check if algorithm execution was successful
if
result
:
# Retrieve output parameters from the result dictionary
if
'
OUTPUT_RASTER
'
in
result
:
output_raster_path
=
result
[
'
OUTPUT_RASTER
'
]
# Add the output raster layer to the map canvas
self
.
iface
.
addRasterLayer
(
str
(
output_raster_path
),
'
merged features
'
)
else
:
# Handle missing or unexpected output
print
(
'
Output raster not found in algorithm result.
'
)
else
:
# Handle algorithm execution failure or cancellation
print
(
'
Algorithm execution was not successful.
'
)
# processing.execAlgorithmDialog('', {})
# self.close_all_dialogs()
def
reduceImage
(
self
):
'''
'''
result
=
processing
.
execAlgorithmDialog
(
'
iamap:reduction
'
,
{})
print
(
result
)
# Check if algorithm execution was successful
if
result
:
# Retrieve output parameters from the result dictionary
if
'
OUTPUT_RASTER
'
in
result
:
output_raster_path
=
result
[
'
OUTPUT_RASTER
'
]
# Add the output raster layer to the map canvas
self
.
iface
.
addRasterLayer
(
str
(
output_raster_path
),
'
reduced features
'
)
else
:
# Handle missing or unexpected output
print
(
'
Output raster not found in algorithm result.
'
)
else
:
# Handle algorithm execution failure or cancellation
print
(
'
Algorithm execution was not successful.
'
)
# processing.execAlgorithmDialog('', {})
def
clusterImage
(
self
):
'''
'''
result
=
processing
.
execAlgorithmDialog
(
'
iamap:cluster
'
,
{})
print
(
result
)
# Check if algorithm execution was successful
if
result
:
# Retrieve output parameters from the result dictionary
if
'
OUTPUT_RASTER
'
in
result
:
output_raster_path
=
result
[
'
OUTPUT_RASTER
'
]
# Add the output raster layer to the map canvas
self
.
iface
.
addRasterLayer
(
str
(
output_raster_path
),
'
clustering
'
)
else
:
# Handle missing or unexpected output
print
(
'
Output raster not found in algorithm result.
'
)
else
:
# Handle algorithm execution failure or cancellation
print
(
'
Algorithm execution was not successful.
'
)
# processing.execAlgorithmDialog('', {})
def
similarityImage
(
self
):
'''
'''
result
=
processing
.
execAlgorithmDialog
(
'
iamap:similarity
'
,
{})
print
(
result
)
# Check if algorithm execution was successful
if
result
:
# Retrieve output parameters from the result dictionary
if
'
OUTPUT_RASTER
'
in
result
:
output_raster_path
=
result
[
'
OUTPUT_RASTER
'
]
# Add the output raster layer to the map canvas
self
.
iface
.
addRasterLayer
(
str
(
output_raster_path
),
'
similarity map
'
)
else
:
# Handle missing or unexpected output
print
(
'
Output raster not found in algorithm result.
'
)
else
:
# Handle algorithm execution failure or cancellation
print
(
'
Algorithm execution was not successful.
'
)
# processing.execAlgorithmDialog('', {})
def
rfImage
(
self
):
'''
'''
result
=
processing
.
execAlgorithmDialog
(
'
iamap:Random_forest
'
,
{})
print
(
result
)
# Check if algorithm execution was successful
if
result
:
# Retrieve output parameters from the result dictionary
if
'
OUTPUT_RASTER
'
in
result
:
output_raster_path
=
result
[
'
OUTPUT_RASTER
'
]
# Add the output raster layer to the map canvas
self
.
iface
.
addRasterLayer
(
str
(
output_raster_path
),
'
random forest map
'
)
else
:
# Handle missing or unexpected output
print
(
'
Output raster not found in algorithm result.
'
)
else
:
# Handle algorithm execution failure or cancellation
print
(
'
Algorithm execution was not successful.
'
)
# processing.execAlgorithmDialog('', {})
def
close_all_dialogs
(
self
):
# Get the main QGIS window (QgisInterface)
qgis_main_window
=
self
.
iface
.
mainWindow
()
# Get all open dialogs associated with the main window
open_dialogs
=
qgis_main_window
.
findChildren
(
QDialog
)
# Iterate through the open dialogs and close them
for
dialog
in
open_dialogs
:
# Check if the dialog is visible (to avoid closing hidden dialogs)
if
dialog
.
isVisible
():
# Close the dialog
dialog
.
close
()
This diff is collapsed.
Click to expand it.
src/iamap/provider.py
deleted
100644 → 0
+
0
−
46
View file @
5b3e5cbe
from
qgis.core
import
QgsProcessingProvider
from
.encoder
import
EncoderAlgorithm
from
.reduction
import
ReductionAlgorithm
from
.clustering
import
ClusterAlgorithm
from
.similarity
import
SimilarityAlgorithm
from
.random_forest
import
RFAlgorithm
from
.icons
import
QIcon_EncoderTool
class
IAMapProvider
(
QgsProcessingProvider
):
def
loadAlgorithms
(
self
,
*
args
,
**
kwargs
):
self
.
addAlgorithm
(
EncoderAlgorithm
())
self
.
addAlgorithm
(
ReductionAlgorithm
())
self
.
addAlgorithm
(
ClusterAlgorithm
())
self
.
addAlgorithm
(
SimilarityAlgorithm
())
self
.
addAlgorithm
(
RFAlgorithm
())
# add additional algorithms here
# self.addAlgorithm(MyOtherAlgorithm())
def
id
(
self
,
*
args
,
**
kwargs
):
"""
The ID of your plugin, used for identifying the provider.
This string should be a unique, short, character only string,
eg
"
qgis
"
or
"
gdal
"
. This string should not be localised.
"""
return
'
iamap
'
def
name
(
self
,
*
args
,
**
kwargs
):
"""
The human friendly name of your plugin in Processing.
This string should be as short as possible (e.g.
"
Lastools
"
, not
"
Lastools version 1.0.1 64-bit
"
) and localised.
"""
return
self
.
tr
(
'
IAMap
'
)
def
icon
(
self
):
"""
Should return a QIcon which is used for your provider inside
the Processing toolbox.
"""
return
QIcon_EncoderTool
def
longName
(
self
)
->
str
:
return
self
.
name
()
This diff is collapsed.
Click to expand it.
src/iamap/utils/geo.py
deleted
100644 → 0
+
0
−
118
View file @
5b3e5cbe
from
typing
import
Callable
,
Union
import
rasterio
import
geopandas
as
gpd
import
numpy
as
np
import
warnings
from
rasterio.io
import
MemoryFile
from
rasterio.merge
import
merge
def
replace_nan_with_zero
(
array
):
array
[
array
!=
array
]
=
0
# Replace NaN values with zero
return
array
def
custom_method_avg
(
merged_data
,
new_data
,
merged_mask
,
new_mask
,
**
kwargs
):
"""
Returns the average value pixel.
cf. https://amanbagrecha.github.io/posts/2022-07-31-merge-rasters-the-modern-way-using-python/index.html
"""
mask
=
np
.
empty_like
(
merged_mask
,
dtype
=
"
bool
"
)
np
.
logical_or
(
merged_mask
,
new_mask
,
out
=
mask
)
np
.
logical_not
(
mask
,
out
=
mask
)
np
.
nanmean
([
merged_data
,
new_data
],
axis
=
0
,
out
=
merged_data
,
where
=
mask
)
np
.
logical_not
(
new_mask
,
out
=
mask
)
np
.
logical_and
(
merged_mask
,
mask
,
out
=
mask
)
np
.
copyto
(
merged_data
,
new_data
,
where
=
mask
,
casting
=
"
unsafe
"
)
def
merge_tiles
(
tiles
:
list
,
dst_path
,
dtype
:
str
=
'
float32
'
,
nodata
=
None
,
#method:str | Callable ='first',
method
:
Union
[
str
,
Callable
]
=
'
first
'
,
):
"""
cf. https://amanbagrecha.github.io/posts/2022-07-31-merge-rasters-the-modern-way-using-python/index.html
"""
file_handler
=
[
rasterio
.
open
(
ds
)
for
ds
in
tiles
]
extents
=
[
ds
.
bounds
for
ds
in
file_handler
]
# Extract individual bounds
lefts
,
bottoms
,
rights
,
tops
=
zip
(
*
extents
)
union_extent
=
(
min
(
lefts
),
# Left
min
(
bottoms
),
# Bottom
max
(
rights
),
# Right
max
(
tops
)
# Top
)
if
method
==
'
average
'
:
method
=
custom_method_avg
# memfile = MemoryFile()
merge
(
datasets
=
file_handler
,
# list of dataset objects opened in 'r' mode
bounds
=
union_extent
,
# tuple
nodata
=
nodata
,
# float
dtype
=
dtype
,
# dtype
# resampling=Resampling.nearest,
method
=
method
,
# strategy to combine overlapping rasters
# dst_path=memfile.name, # str or PathLike to save raster
dst_path
=
dst_path
,
# dst_kwds={'blockysize':512, 'blockxsize':512} # Dictionary
)
def
get_mean_sd_by_band
(
path
,
force_compute
=
True
,
ignore_zeros
=
True
):
'''
Reads metadata or computes mean and sd of each band of a geotiff.
If the metadata is not available, mean and standard deviation can be computed via numpy.
Parameters
----------
path : str
path to a geotiff file
ignore_zeros : boolean
ignore zeros when computing mean and sd via numpy
Returns
-------
means : list
list of mean values per band
sds : list
list of standard deviation values per band
'''
src
=
rasterio
.
open
(
path
)
means
=
[]
sds
=
[]
if
force_compute
:
for
band
in
range
(
1
,
src
.
count
+
1
):
arr
=
src
.
read
(
band
)
arr
=
replace_nan_with_zero
(
arr
)
if
ignore_zeros
:
mean
=
np
.
ma
.
masked_equal
(
arr
,
0
).
mean
()
sd
=
np
.
ma
.
masked_equal
(
arr
,
0
).
std
()
else
:
mean
=
np
.
mean
(
arr
)
sd
=
np
.
std
(
arr
)
means
.
append
(
float
(
mean
))
sds
.
append
(
float
(
sd
))
else
:
for
band
in
range
(
1
,
src
.
count
+
1
):
try
:
tags
=
src
.
tags
(
band
)
if
'
STATISTICS_MEAN
'
in
tags
and
'
STATISTICS_STDDEV
'
in
tags
:
mean
=
float
(
tags
[
'
STATISTICS_MEAN
'
])
sd
=
float
(
tags
[
'
STATISTICS_STDDEV
'
])
means
.
append
(
mean
)
sds
.
append
(
sd
)
else
:
raise
KeyError
(
"
Statistics metadata not found.
"
)
except
KeyError
:
warnings
.
warn
(
"
Statistics metadata not found and computation not enabled.
"
,
UserWarning
)
except
Exception
as
e
:
print
(
f
"
Error processing band
{
band
}
:
{
e
}
"
)
src
.
close
()
return
means
,
sds
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment