Skip to content

Commit

Permalink
Merge pull request #134 from vermeulendivan/dev_composite_checkout
Browse files Browse the repository at this point in the history
Composite checkout function for orders
  • Loading branch information
john-dupuy authored Jul 19, 2023
2 parents 22a8efe + d9d78d8 commit 665b220
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 22 deletions.
133 changes: 122 additions & 11 deletions planet_explorer/gui/pe_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
iface,
ENABLE_CLIP_SETTING,
ENABLE_HARMONIZATION_SETTING,
ENABLE_COMPOSITE,
ENABLE_STAC_METADATA,
SETTINGS_NAMESPACE,
)
Expand Down Expand Up @@ -134,6 +135,7 @@ def __init__(self, bundleid, bundle, item_type):
)
self.can_harmonize = bundle.get("canHarmonize", False)
self.can_clip = bundle.get("canClip", False)

self.rectified = bundle["rectification"] == "orthorectified"
bands = []
asset_def = PlanetClient.getInstance().asset_types_for_item_type_as_dict(
Expand Down Expand Up @@ -460,6 +462,9 @@ def __init__(self, item_type, bundle_type, images, add_clip, add_harmonize):
self.bundle_type = bundle_type
self.images = images
self.add_clip = add_clip

self.add_composite = True

self.add_harmonize = add_harmonize
self.stac_order = QSettings().value(
f"{SETTINGS_NAMESPACE}/{ENABLE_STAC_METADATA}", False, type=bool
Expand Down Expand Up @@ -508,6 +513,7 @@ def populate_details(self):
layout.setColumnStretch(0, 1)
layout.setColumnStretch(2, 1)
self.chkClip = None
self.chkComposite = None
self.chkHarmonize = None
if self.add_clip:
layout.addWidget(QLabel("<b>Clipping</b>"), 0, 1, Qt.AlignCenter)
Expand All @@ -521,14 +527,63 @@ def populate_details(self):
self.chkClip.setChecked(str(enabled).lower() == str(True).lower())
self.chkClip.stateChanged.connect(self.checkStateChanged)
layout.addWidget(self.chkClip, 2, 1, Qt.AlignCenter)

if self.add_composite:
layout.addWidget(QLabel("<b>Composite Items</b>"), 3, 1, Qt.AlignCenter)
description_label = QLabel(
"The "
"<a style='color: #50a94e; text-decoration: none;' "
"href='https://developers.planet.com/apis/orders/tools/#composite'>"
"Composite tool</a>"
" allows your to composite a "
"set of images into a single output"
)
layout.addWidget(
description_label,
4,
1,
Qt.AlignCenter,
)
description_label.setOpenExternalLinks(True)

self.chkComposite = QCheckBox("Enable composite")
enabled = QSettings().value(
f"{SETTINGS_NAMESPACE}/{ENABLE_COMPOSITE}", False
)
self.chkComposite.setChecked(str(enabled).lower() == str(True).lower())
self.chkComposite.stateChanged.connect(self.compositeStateChanged)
layout.addWidget(self.chkComposite, 5, 1, Qt.AlignCenter)

self.radio_btn_all = QRadioButton("All items")
self.radio_btn_strip = QRadioButton("By strip")
self.radio_btn_all.setChecked(True)

# Show/hide composite radio buttons
if self.chkComposite.isChecked():
self.radio_btn_all.setEnabled(True)
self.radio_btn_strip.setEnabled(True)

self.radio_btn_all.setVisible(True)
self.radio_btn_strip.setVisible(True)

else:
self.radio_btn_all.setEnabled(False)
self.radio_btn_strip.setEnabled(False)

self.radio_btn_all.setVisible(False)
self.radio_btn_strip.setVisible(False)

layout.addWidget(self.radio_btn_all, 6, 1, Qt.AlignCenter)
layout.addWidget(self.radio_btn_strip, 7, 1, Qt.AlignCenter)

if self.add_harmonize:
layout.addWidget(QLabel("<b>Harmonization</b>"), 3, 1, Qt.AlignCenter)
layout.addWidget(QLabel("<b>Harmonization</b>"), 8, 1, Qt.AlignCenter)
layout.addWidget(
QLabel(
"Radiometrically harmonize imagery captured by one satellite "
"instrument type to imagery capture by another"
),
4,
9,
1,
Qt.AlignCenter,
)
Expand All @@ -538,19 +593,19 @@ def populate_details(self):
)
self.chkHarmonize.setChecked(str(enabled).lower() == str(True).lower())
self.chkHarmonize.stateChanged.connect(self.checkStateChanged)
layout.addWidget(self.chkHarmonize, 5, 1, Qt.AlignCenter)
layout.addWidget(self.chkHarmonize, 10, 1, Qt.AlignCenter)

metadata_widget = PlanetOrderReviewMetadataWidget(self.stac_order)
metadata_widget.stac_metadata_box_clicked.connect(self._stac_box_clicked)

layout.addWidget(metadata_widget, 6, 1, Qt.AlignCenter)
layout.addWidget(metadata_widget.description_label, 7, 1, Qt.AlignCenter)
layout.addWidget(metadata_widget.stac_box, 8, 1, Qt.AlignCenter)
layout.addWidget(metadata_widget, 11, 1, Qt.AlignCenter)
layout.addWidget(metadata_widget.description_label, 12, 1, Qt.AlignCenter)
layout.addWidget(metadata_widget.stac_box, 13, 1, Qt.AlignCenter)

layout.addWidget(QLabel("<b>Review Items</b>"), 9, 1, Qt.AlignCenter)
layout.addWidget(QLabel("<b>Review Items</b>"), 14, 1, Qt.AlignCenter)
layout.addWidget(
QLabel("We recommend deselecting items that appear to have no pixels"),
10,
15,
1,
Qt.AlignCenter,
)
Expand All @@ -564,13 +619,28 @@ def populate_details(self):
col = i % 4 + 1
sublayout.addWidget(w, row, col)
self.imgWidgets.append(w)
layout.addLayout(sublayout, 11, 1, Qt.AlignCenter)
layout.addLayout(sublayout, 16, 1, Qt.AlignCenter)

self.widgetDetails.setLayout(layout)

def checkStateChanged(self):
self.selectedImagesChanged.emit()

def compositeStateChanged(self):
# Show/hide composite radio buttons
if self.chkComposite.isChecked():
self.radio_btn_all.setEnabled(True)
self.radio_btn_strip.setEnabled(True)

self.radio_btn_all.setVisible(True)
self.radio_btn_strip.setVisible(True)
else:
self.radio_btn_all.setEnabled(False)
self.radio_btn_strip.setEnabled(False)

self.radio_btn_all.setVisible(False)
self.radio_btn_strip.setVisible(False)

def selected_images(self):
return [w.image for w in self.imgWidgets if w.selected()]

Expand All @@ -586,6 +656,20 @@ def harmonize(self):
else:
return self.chkHarmonize.isChecked()

def composite(self):
if self.chkComposite is None:
return False
else:
return self.chkComposite.isChecked()

def getCompositeType(self):
if self.radio_btn_all.isChecked():
# Will composite all images
return "order"
else:
# Will only composite each strip
return "strip_id"

def _btnDetailsClicked(self):
if self.widgetDetails.isVisible():
self.widgetDetails.hide()
Expand Down Expand Up @@ -871,6 +955,7 @@ def _process_orders(self):
aoi = None
if self.tool_resources.get("aoi") is not None:
aoi = json.loads(self.tool_resources.get("aoi"))

orders = []
for item_type, widget in self._item_type_widgets.items():
for bundle in widget.bundles():
Expand Down Expand Up @@ -901,6 +986,10 @@ def _process_orders(self):
tools = []
if w.clipping():
tools.append({"clip": {"aoi": aoi}})
if w.composite():
# 'order' or 'strip_id' for 'group_by'
composite_type = w.getCompositeType()
tools.append({"composite": {"group_by": composite_type}})
if w.harmonize():
tools.append({"harmonize": {"target_sensor": "Sentinel-2"}})
if bundle["filetype"] == "NITF":
Expand All @@ -911,8 +1000,30 @@ def _process_orders(self):
responses_ok = True
for order in orders:
resp = self._p_client.create_order(order)
responses_ok = responses_ok and resp
send_analytics_for_order(order)
resp_json = resp.json()

# If the order request failed
if resp.status_code >= 400:
order_name = order["name"]

if resp_json and resp_json["general"][0]["message"]:
# Error message received from response
err_message = resp_json["general"][0]["message"]
else:
# If no error message has been received
err_message = "An error occurred for the order."

self.bar.pushMessage(
order_name,
err_message,
Qgis.Warning,
)

responses_ok = False
else:
# Order were a success
responses_ok = responses_ok and resp_json
send_analytics_for_order(order)

if responses_ok:
self.bar.pushMessage(
Expand Down
20 changes: 15 additions & 5 deletions planet_explorer/gui/pe_orders_monitor_dockwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,15 +428,25 @@ def add_to_map(self):
list_files = manifest_data["files"]
for json_file in list_files:
media_type = json_file["media_type"]

raster_types = ["image/tiff", "application/vnd.lotus-notes"]

if media_type in raster_types:
annotations = json_file["annotations"]
asset_type = annotations["planet/asset_type"]
if asset_type.endswith("_udm") or asset_type.endswith("_udm2"):
# Skips all 'udm' asset rasters
continue
asset_type_key = "planet/asset_type"

if asset_type_key in annotations:
asset_type = annotations[asset_type_key]
if asset_type.endswith("_udm") or asset_type.endswith("_udm2"):
# Skips all 'udm' asset rasters
continue
else:
# A workaround for composite
image_path = json_file["path"]
if not image_path.endswith(
"composite.tif"
) and not image_path.endswith("composite_file_format.ntf"):
# Skips if it's not a composite file
continue

image_path = json_file["path"]
image_dir = "{}/{}".format(final_path, image_path)
Expand Down
2 changes: 2 additions & 0 deletions planet_explorer/pe_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def analytics_track(event, properties=None):


item_type_names = {
"PSScene": "planetscope_scene",
"PSScene4Band": "planetscope_scene",
"PSScene3Band": "planetscope_scene",
"PSOrthoTile": "planetscope_ortho",
Expand Down Expand Up @@ -150,6 +151,7 @@ def send_analytics_for_preview(imgs):
def send_analytics_for_order(order):
product = order["products"][0]
name = item_type_names.get(product["item_type"])

if name is not None:
analytics_track(
SCENE_ORDER_PLACED,
Expand Down
1 change: 1 addition & 0 deletions planet_explorer/pe_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
DEFAULT_ORDERS_FOLDERNAME = "planet_orders"
ENABLE_CLIP_SETTING = "enableClip"
ENABLE_STAC_METADATA = "enableStacMetadata"
ENABLE_COMPOSITE = "enableComposite"
ENABLE_HARMONIZATION_SETTING = "enableHarmonization"

BASE_URL = "https://www.planet.com"
Expand Down
3 changes: 2 additions & 1 deletion planet_explorer/planet_api/p_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ def create_order(self, request):
headers = {"X-Planet-App": "qgis"}
session = PlanetClient.getInstance().dispatcher.session
res = session.post(url, auth=(api_key, ""), json=request, headers=headers)
return res.json()

return res

def update_search(self, request, searchid):
body = json.dumps(request)
Expand Down
30 changes: 25 additions & 5 deletions planet_explorer/planet_api/p_order_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,32 @@ def images_from_manifest(self, manifest_file):
images = []
for img in manifest["files"]:
if img["media_type"] == "image/tiff":
images.append(
(
os.path.join(base_folder, img["path"]),
img["annotations"]["planet/item_type"],
annotations = img["annotations"]
asset_type_key = "planet/asset_type"

if asset_type_key in annotations:
images.append(
(
os.path.join(base_folder, img["path"]),
img["annotations"]["planet/item_type"],
)
)
)
else:
# A workaround for composite
image_path = img["path"]
if not image_path.endswith(
"composite.tif"
) and not image_path.endswith("composite_file_format.ntf"):
# Skips if it's not a composite file
continue
else:
# Adds the composite file
images.append(
(
os.path.join(base_folder, img["path"]),
"composite", # Item type
)
)
return images

def finished(self, result):
Expand Down

0 comments on commit 665b220

Please sign in to comment.