Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial development of the Custom Overlays feature #833

Closed
wants to merge 2 commits into from

Conversation

ted-at-rtr
Copy link
Collaborator

This feature fulfills the following requirements:

  • A customer that does not have internet access for their JAIA system
  • They put a GEOTiff on to their hub  
  • They open JCC and go to the layers panel
  • In the layers panel there is an accordion available to overlay GEOTiff called "Custom Overlay"
  • The customer presses a button to load a GEOTiff that is on the hub
  • The GEOTiff is now displayed on the JCC

Please note:

  • The doc at src/doc/markdown/feature-custom_overlays.md lists some prerequisites that you'll need to fulfill in order to use the new feature.
  • That doc also asks several questions (labeled with "Question"), particularly about the prerequisites.
  • Note that we've also added packages to the packages.json file - we're not sure if the rebuild procedure automatically does an "npm install", so if it doesn't and you build this in an existing sandbox then this is something you might have to do manually.

@michael-jaia
Copy link
Collaborator

Hey Ted, I started playing around with this pull request. It was cool to see GeoTIFFs appear on the map. I did notice in testing that one of my TIFFs (zurich.tiff) caused the JCC to become unresponsive while it loaded it in. Do you know if there is a max size on the TIFF file? Here are my sample files below:
tiffs.zip

@ted-at-rtr
Copy link
Collaborator Author

What you're seeing is not surprising, given the large number of format combinations that can be used in GeoTIFFs. When we asked for example GeoTIFFs that might be used, we did that so we could make sure the code could deal with the data formats in those example files. Unfortunately, both the GeoTIFFs you provided fall outside the abilities of what is currently coded. The code can be extended to handle these two GeoTIFFs, but you should be aware of some gotchas.

First, to answer your question directly: Re: "Do you know if there is a max size on the TIFF file?" I had not previously attempted to characterize this, but my tests of your images seem to point to a 38,000,000 pixel limit (e.g. a square image around 6,000x6,000).

Second, here are observations about the test GeoTIFFs you are using:

The bands in "sample.tif" are labelled "Gray", "Undefined, and "Undefined", but appear to have an RGB raster. We may be wrong about this, but assuming it is RGB data, note that instead of using uint8 values for the RGB band values it uses uint16. The values seem to be scaled from 0 - 11000 (roughly), so it's likely not a simple matter of "take the high byte"; we'd have to play with it to see how it looks, but I'm betting that the RGB values would need to be scaled by 255/11000, and we'd need to add a bit of code for that kind of scaling.

"zurich.tif" is a 15,000x15,000 pixel image. Because we're dealing with 2D images, operations on these images are O(N^2) complexity, and when you get to 15,000 pixels you start noticing that. The browser is not permanently unresponsive, it just takes a long time to crunch that image. However, once it does finish crunching it, it can't display it as it exceeds the 6Kx6K capability. The majority of the time falls into three buckets: reading the raster using the GeoTIFF NPM, converting the raster to a canvas in bespoke JavaScript code, and converting the canvas data into a form that the OpenLayers Static object can read as a URL. If you need to handle images this large, I believe that this can be fixed in multiple ways: The geotiff NPM supports WebWorker pools, which the CustomLayers.js code currently doesn't enable; IIRC WebWorkers don't block the main thread. Further, we could put the code that converts the raster to a canvas into a WebWorker. Last, it may be possible that we can use a "blob" URL to pass the image into the OpenLayers Static object.

Also, we were wondering about what kind of automatic Q/A is built into your CI pipeline, and if this feature requires automatic tests.

@michael-jaia
Copy link
Collaborator

Hey Ted, thanks for the response. That is good to know about the approximate pixel limit. I did a little more testing today and the TIFFs Matt sent you worked well. I tried a TIFF from the Tasmania exercise that is within the pixel limit, but it did not process correctly. When the TIFF meta.json file is created, the proj4 value is empty. I tried running it with the empty string and with a "+proj=longlat +datum=WGS84 +no_defs". I'm not sure if anything about the TIFF stands out to you or if there is something we need to tweak about the processing code. Let me know what you think!

As for our CI, it is configured to check that all of the code builds successfully before a branch can be merged. We have not integrated any additional requirements yet.

AUS00167.zip

@ted-at-rtr
Copy link
Collaborator Author

ted-at-rtr commented Apr 26, 2024

Hi Michael, the AUS00167P1.tif file appears to be a normal TIFF file, not a GeoTIFF. I think our documentation said "Note that normal TIFF files lacking geospatial data are not supported."

Here's why I think this is a normal TIFF file: If you run the gdalinfo utility on it (e.g. gdalinfo AUS00167P1.tif), notice that there is no GeoTIFF metadata. BTW, don't be fooled by the first line of gdalinfo output, which will always be Driver: GTiff/GeoTIFF for any TIFF file, both plain or GeoTIFF-tagged.

This limitation is in the geotiff NPM package we use to load TIFF files; it generates an exception if you ask for the extent of a normal TIFF file. Our not handling that exception could be considered a bug, because the exception handler I currently have in place is over the entire load process, and this "bad" TIFF causes the entire Custom Overlay loading to abort. I should add an additional per-overlay exception handler to make sure the other overlays are properly loaded.

Note that if I correct this bug to allow us to display non-GeoTIFF TIFF files, you would then need to edit the .meta.json file to include the both the projection and extent fields. (Remember, you can also specify epsg instead ofprojection.)

Therefore, I should update geotiff_format.py to recognize non-GeoTIFF TIFF files and write out blank projection, epsg , and extent fields into the generated .meta.json file. And I should print a warning pointing out your need to fill in the proper projection and extent fields; this warning should also appear for JPEG/GIF files as well.

Last, I did not have any TIFF file examples with this file's RGB encoding (which is one band of a palette index instead of three bands of RGB). Therefore, the CustomOverlay.js code isn't going to recognize this file properly - it will likely try to display it as a gray-scale image with the value being the palette index (which will then appear nonsensical). Until I tweak CustomOverlay.js code to deal with this, you can work around this by asserting that the image is an RGB and has three bands. Side note: IIRC, the zurich.tif file also had that encoding, and would similarly fail if it wasn't so big.

So, I can get AUS00167P1.tif to display properly using the following steps

  1. Insert the projection and extent into the TIFF file to make it a GeoTIFF file named AUS00167P1G.tif. Do this by running the following command:
gdal_translate -a_srs EPSG:4326 -a_ullr 146.814691 -41.128482 146.892519 -41.161841 AUS00167P1.tif AUS00167P1G.tif
  1. Extract the metadata as normal:
bash ~/jaiabot/scripts/geotiff_scan.sh AUS00167P1G.tif
  1. Edit AUS00167P1G.tif.meta.json to declare its raster as three bands of RGB:
{
    "description": "Tasmania Overlay",
    "extension": ".tif",
    "proj4": "+proj=longlat +datum=WGS84 +no_defs",
    "isRGB": true,
    "noDataValueRGB": [
        0,
        0,
        0
    ],
    "bands": [
        {
            "band": 1,
            "colorInterpretation": "Red",
            "noDataValue": null
        },
        {
            "band": 2,
            "colorInterpretation": "Green",
            "noDataValue": null
        },
        {
            "band": 3,
            "colorInterpretation": "Blue",
            "noDataValue": null
        }
    ]
}
  1. Make sure there is no metadata for AUS00167P1.tif because that will cause an exception and terminate the Custom Overlay loading.
rm AUS00167P1.tif.meta.json

@michael-jaia
Copy link
Collaborator

Hi Ted, thank you for the insight. I did not realize the geotiff/tiff difference in this case. I should have caught that in the documentation! Since it may not be obvious whether a tiff file is a geotiff or a regular tiff to a user, I think it would be a helpful to handle the errors that arise with regular tiffs, so they do not cause the Custom Overlays panel to disappear. What you mentioned here:

Therefore, I should update geotiff_format.py to recognize non-GeoTIFF TIFF files and write out blank projection, epsg , and extent fields into the generated .meta.json file. And I should print a warning pointing out your need to fill in the proper projection and extent fields; this warning should also appear for JPEG/GIF files as well.

sounds like it would be a nice addition. Just so we are on the same page, where you wrote GIF did you mean to type PNG?

@michael-jaia
Copy link
Collaborator

michael-jaia commented May 10, 2024

Closing this pull request since the updated version lives in: #856

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants