Last active
May 26, 2020 00:35
-
-
Save foobarbecue/0f1b3706738d5069c724648e0897a32b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# NACpipeline Argo workflow | |
# Aaron Curtis | |
# Concurrency rules: Write files as temporary, then move to intended dest. Check for existing output before starting. | |
apiVersion: argoproj.io/v1alpha1 | |
kind: Workflow | |
metadata: | |
generateName: nac-stereo- | |
spec: | |
entrypoint: nac-mosaic | |
volumes: | |
- name: nac-volume | |
hostPath: | |
path: /c/nacpldata4 | |
type: DirectoryOrCreate | |
arguments: | |
parameters: | |
- name: west | |
- name: east | |
- name: south | |
- name: north | |
templates: | |
# Dummy template with reusable parts for references in stereo templates. Not to be run. | |
- name: dummy-stereo-template | |
inputs: &right-left-inps | |
parameters: | |
- name: right-prod-id | |
- name: left-prod-id | |
container: &nacpl-container | |
image: lmmp-local/lmmp-container | |
imagePullPolicy: IfNotPresent | |
volumeMounts: | |
- name: nac-volume | |
mountPath: /data/nac | |
- name: dummy-stereo-dag-template | |
inputs: *right-left-inps | |
dag: | |
tasks: | |
- name: dummy-task | |
template: dummy-stereo-template | |
arguments: &left-right-arguments-from-inputs | |
parameters: | |
- name: right-prod-id | |
value: "{{inputs.parameters.right-prod-id}}" | |
- name: left-prod-id | |
value: "{{inputs.parameters.left-prod-id}}" | |
# Dummy template with reusable parts for references in mosaic templates. Not to be run. | |
- name: dummy-mosaic-template | |
inputs: &bounding-box-arguments-from-inputs | |
parameters: | |
- name: west | |
value: "{{workflow.parameters.west}}" | |
- name: east | |
value: "{{workflow.parameters.east}}" | |
- name: south | |
value: "{{workflow.parameters.south}}" | |
- name: north | |
value: "{{workflow.parameters.north}}" | |
container: *nacpl-container | |
# Given a bounding box {{west}}, {{east}}, {{south}}, {{north}} find appropriate NAC stereo pairs and create: | |
# - stereo DEM mosaic covering the box at /data/nac/{{west}}_{{east}}_{{south}}_{{north}}DEM-mosaic.tif | |
# - orthophoto mosaic covering the box at /data/nac/{{west}}_{{east}}_{{south}}_{{north}}DRG-mosaic.tif | |
# - list of NAC pairs to use at /data/nac/{{west}}_{{east}}_{{south}}_{{north}}pairs.txt | |
- name: nac-mosaic | |
inputs: *bounding-box-arguments-from-inputs | |
parallelism: 3 | |
steps: | |
- - name: find-pairs | |
template: find-pairs | |
arguments: *bounding-box-arguments-from-inputs | |
- - name: nac-stereo | |
template: nac-stereo | |
arguments: | |
parameters: | |
- name: left-prod-id | |
value: "{{item.left}}" | |
- name: right-prod-id | |
value: "{{item.right}}" | |
withParam: "{{steps.find-pairs.outputs.result}}" | |
continueOn: | |
failed: true | |
- - name: merge-dems | |
template: merge-dems | |
arguments: | |
parameters: | |
- name: pair-ids | |
value: "{{steps.find-pairs.outputs.result}}" | |
- - name: color-hillshade | |
template: color-hillshade | |
arguments: | |
artifacts: | |
- name: dem | |
from: "{{steps.merge-dems.outputs.artifacts.dem}}" | |
- name: merge-orthoimages # TODO don't need to wait for hillshade or dem | |
template: merge-orthoimages | |
arguments: | |
parameters: | |
- name: pair-ids | |
value: "{{steps.find-pairs.outputs.result}}" | |
- name: find-pairs | |
inputs: *bounding-box-arguments-from-inputs | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
. activate NAC_pl_env_py3 | |
python /nacpl/find_stereo_pairs.py \ | |
--west={{inputs.parameters.west}} \ | |
--east={{inputs.parameters.east}} \ | |
--south={{inputs.parameters.south}} \ | |
--north={{inputs.parameters.north}} \ | |
--find-covering=True | |
# Given two nac product ids, right-prod-id and left-prod-id, initiate workflow to create: | |
# - stereo DEM at /data/nac/{{left-prod-id}}xx{{right-prod-id}}-median-DEM.tif | |
# - orthophoto at /data/nac/{{left-prod-id}}xx{{right-prod-id}}-median-DRG.tif | |
# Also create some useful extra products: | |
# - Downloaded .IMG files in /data/nac/ | |
# - ISIS-ingested .cub files in /data/nac/ | |
# - Intermediate data products in /data/nac/{{left-prod-id}}xx{{right-prod-id}} | |
- name: nac-stereo | |
parallelism: 3 | |
inputs: *left-right-arguments-from-inputs | |
dag: | |
tasks: | |
- name: dl-ingest-right | |
template: dl-ingest-nac | |
arguments: | |
parameters: [{name: prod-id, value: "{{inputs.parameters.right-prod-id}}"}] | |
- name: dl-ingest-left | |
template: dl-ingest-nac | |
arguments: | |
parameters: [{name: prod-id, value: "{{inputs.parameters.left-prod-id}}"}] | |
- name: map-project | |
template: map-project | |
arguments: *left-right-arguments-from-inputs | |
dependencies: [dl-ingest-right, dl-ingest-left] | |
- name: stereo | |
template: stereo | |
arguments: *left-right-arguments-from-inputs | |
dependencies: [map-project] | |
- name: download-lola | |
template: download-lola | |
arguments: *left-right-arguments-from-inputs | |
dependencies: [map-project] | |
- name: align | |
template: align | |
arguments: *left-right-arguments-from-inputs | |
dependencies: [stereo, download-lola] | |
# Before this point, intermediate data products are considered re-usable and should be stored in a common location to | |
# prevent re-processing in future mosaics | |
- name: generate-DEM-and-orthoimages | |
template: generate-DEM-and-orthoimages | |
arguments: *left-right-arguments-from-inputs | |
dependencies: [align] | |
# Given a nac product id prod-id, initiate workflow download and ingest NAC into ISIS, creating: | |
# - Downloaded .IMG file in /data/nac/{{prod-id}} | |
# - ISIS-ingested .cub file in /data/nac/{{prod-id}} | |
- name: dl-ingest-nac | |
inputs: | |
parameters: | |
- name: prod-id | |
dag: | |
tasks: | |
- name: download-nac | |
template: download-nac | |
arguments: | |
parameters: | |
- name: prod-id | |
value: "{{inputs.parameters.prod-id}}" | |
- name: img2cub | |
template: img2cub | |
arguments: | |
parameters: | |
- name: prod-id | |
value: "{{inputs.parameters.prod-id}}" | |
dependencies: [download-nac] | |
- name: calibrate | |
template: calibrate | |
arguments: | |
parameters: | |
- name: prod-id | |
value: "{{inputs.parameters.prod-id}}" | |
dependencies: [img2cub] | |
# Download a NAC image if doesn't exist and store to /data/nac on NFS | |
# Script downloads to a temporary file and then moves it into place | |
- name: download-nac | |
inputs: | |
parameters: | |
- name: prod-id | |
retryStrategy: | |
limit: 3 | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
. activate NAC_pl_env_py3 | |
if ! test -f /data/nac/{{inputs.parameters.prod-id}}.IMG | |
then | |
python /nacpl/download_NAC.py {{inputs.parameters.prod-id}} /data/nac | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Download LOLA data for NAC image if it hasn't already been downloaded | |
# Saves image at /data/nac/[right-prod-id]xx[left-prod-id]_lola.csv | |
# TODO see if can use abs paths and avoid cd | |
# NOTE breaks concurrency rule but write time for file is short enough that collision unlikely | |
- name: download-lola | |
inputs: *right-left-inps | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if ! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/*_lola.csv | |
then | |
. activate NAC_pl_env_py3 | |
cd /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}} | |
python /nacpl/download_LOLA.py \ | |
map-{{inputs.parameters.left-prod-id}}.map.cub map-{{inputs.parameters.right-prod-id}}.map.cub \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}} | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Convert IMG to ISIS cube if the cube doesn't already exist | |
- name: img2cub | |
inputs: | |
parameters: | |
- name: prod-id | |
retryStrategy: | |
limit: 3 | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if ! test -f /data/nac/{{inputs.parameters.prod-id}}.cub | |
then | |
mkdir -p /data/nac/tmp/ | |
echo "Running lronac2isis FROM=/data/nac/{{inputs.parameters.prod-id}}.IMG TO=/data/nac/tmp/{{inputs.parameters.prod-id}}.cub" | |
lronac2isis -v FROM=/data/nac/{{inputs.parameters.prod-id}}.IMG TO=/data/nac/tmp/{{inputs.parameters.prod-id}}.cub | |
mv /data/nac/tmp/{{inputs.parameters.prod-id}}.cub /data/nac/ | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Run spiceinit, lronaccal, and lronacecho and produce a .cal.cub if one doesn't already exist | |
- name: calibrate | |
inputs: | |
parameters: | |
- name: prod-id | |
retryStrategy: | |
limit: 3 | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if ! test -f /data/nac/{{inputs.parameters.prod-id}}.cal.cub | |
then | |
spiceinit FROM=/data/nac/{{inputs.parameters.prod-id}}.cub web=yes | |
lronaccal FROM=/data/nac/{{inputs.parameters.prod-id}}.cub TO=/tmp/{{inputs.parameters.prod-id}}.cal.cub | |
lronacecho FROM=/tmp/{{inputs.parameters.prod-id}}.cal.cub TO=/data/nac/tmp/{{inputs.parameters.prod-id}}.cal.cub | |
mv /data/nac/tmp/{{inputs.parameters.prod-id}}.cal.cub /data/nac/{{inputs.parameters.prod-id}}.cal.cub | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Project the images to the best common resolution | |
- name: map-project | |
inputs: *right-left-inps | |
retryStrategy: | |
limit: 3 | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if (! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map-{{inputs.parameters.left-prod-id}}.map.cub && \ | |
! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map-{{inputs.parameters.right-prod-id}}.map.cub) | |
then | |
. activate NAC_pl_env_py3 | |
cd /StereoPipeline-2.6.2-2019-06-17-x86_64-Linux/bin | |
cam2map4stereo.py \ | |
--prefix=/data/nac/tmp/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map \ | |
/data/nac/{{inputs.parameters.left-prod-id}}.cal.cub \ | |
/data/nac/{{inputs.parameters.right-prod-id}}.cal.cub | |
mkdir -p /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/ | |
mv /data/nac/tmp/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map*map.cub \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/ | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Do stereo reconstruction between the pairs if a stereo point cloud doesn't exist yet for them | |
- name: stereo | |
inputs: *right-left-inps | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if ! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/stereo-PC.tif | |
then | |
parallel_stereo \ | |
--processes=10 \ | |
--threads-singleprocess=10 \ | |
--alignment-method=none \ | |
--individually-normalize \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map-{{inputs.parameters.right-prod-id}}.map.cub \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map-{{inputs.parameters.left-prod-id}}.map.cub \ | |
/data/nac/tmp/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/stereo | |
mv /data/nac/tmp/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/* \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/ | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Align the point cloud to LOLA | |
- name: align | |
inputs: *right-left-inps | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if ! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/pc_align-trans_reference.tif | |
then | |
pc_align \ | |
--max-displacement 1200 \ | |
--csv-format '1:lon 2:lat 3:height_above_datum' \ | |
--save-inv-transformed-reference-points \ | |
--threads 10 \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/stereo-PC.tif \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/map-{{inputs.parameters.left-prod-id}}xxmap-{{inputs.parameters.right-prod-id}}_lola.csv \ | |
-o /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/tmp/pc_align | |
mv /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/tmp/pc_align*.tif \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/ | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Convert the point cloud to a DEM and an orthoimage | |
- name: generate-DEM-and-orthoimages | |
inputs: *right-left-inps | |
retryStrategy: | |
limit: 3 | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
if (! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}*DEM.tif && \ | |
! test -f /data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}*DRG.tif) | |
then | |
point2dem \ | |
-o /data/nac/tmp/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}} \ | |
--t_srs http://spatialreference.org/ref/iau2000/30100/ \ | |
--nodata -9999 \ | |
--filter median \ | |
--median-filter-params 40 20 \ | |
--tif-compress LZW \ | |
--threads 10 \ | |
--orthoimage \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/stereo-L.tif \ | |
/data/nac/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}/pc_align-trans_reference.tif | |
mv /data/nac/tmp/{{inputs.parameters.left-prod-id}}xx{{inputs.parameters.right-prod-id}}*.tif \ | |
/data/nac/ | |
else | |
echo "Skipping step because output file already exists" | |
fi | |
# Template to merge DEMs | |
# mosaic_merge.py calls ASP dem_mosaic | |
- name: merge-dems | |
inputs: | |
parameters: | |
- name: pair-ids | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
#TODO tidy up following section, maybe get rid of bash substitution | |
source: | | |
. activate NAC_pl_env_py3 | |
mkdir -p /data/nac/merged | |
python /nacpl/mosaic_merge.py $'{{inputs.parameters.pair-ids}}' DEM /data/nac /tmp/ | |
# Copy to shared storage, ending the DEM with DEM.tif instead of tile-0.tif | |
DEM_FILENAME=( /tmp/*tile-0.tif ) | |
DEM_FILENAME_CORRECTED=${DEM_FILENAME/tile-0/DEM} | |
cp /tmp/*tile-0.tif /data/nac/merged/${DEM_FILENAME_CORRECTED/\/tmp/} | |
# Move the file so it can be output as an artifact | |
mv /tmp/*tile-0.tif /tmp/merged_DEM.tif | |
outputs: | |
artifacts: | |
- name: dem | |
path: /tmp/merged_DEM.tif | |
# Template to render a color hillshade | |
- name: color-hillshade | |
inputs: | |
artifacts: | |
- name: dem | |
path: /tmp/merged_DEM.tif | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
. activate NAC_pl_env_py3 | |
gdalwarp -s_srs "EPSG:104903" \ | |
-t_srs "+proj=eqc +lat_ts={{workflow.parameters.north}} +lat_0={{workflow.parameters.north}} +lon_0={{workflow.parameters.west}} +x_0=0 +y_0=0 +a=1737400 +b=1737400 +units=m +no_defs" \ | |
/tmp/merged_DEM.tif /tmp/merged_DEM_eqc.tif | |
gdaldem hillshade /tmp/merged_DEM_eqc.tif /tmp/merged_hillshade.tif | |
gdaldem color-relief /tmp/merged_DEM_eqc.tif /nacpl/elevation_colors.txt /tmp/merged_color-relief.tif | |
hsv_merge -o /tmp/color_hillshade.tif /tmp/merged_color-relief.tif /tmp/merged_hillshade.tif | |
outputs: | |
artifacts: | |
- name: color-hillshade | |
path: /tmp/ #TODO save in volume? | |
# Template to merge orthophotos (digital raster graphics, DRGs) | |
# mosaic_merge.py calls Orfeo Toolbox Mosaic (otbcli_Mosaic) | |
- name: merge-orthoimages | |
inputs: | |
parameters: | |
- name: pair-ids | |
script: | |
<<: *nacpl-container | |
command: [bash] | |
source: | | |
. activate NAC_pl_env_py3 | |
mkdir -p /data/nac/merged | |
export OTB_MAX_RAM_HINT=1024 | |
python /nacpl/mosaic_merge.py $'{{inputs.parameters.pair-ids}}' DRG /data/nac /tmp | |
outputs: | |
artifacts: | |
- name: orthoimage | |
path: /tmp/ #TODO save in volume? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment