Solved

How to apply "clear_percent" filter after clipping the image?


Badge +1

I am downloading clipped ortho_analytic_sr image and its udm for the list of geojson geometries. I need to apply several filters (date, clear_percent, and asset) before downloading. I also need to clip the images to reduce my storage cost. However, I cannot find a way to clip the image first and apply the clear_percent filter without downloading the whole image first.

By filtering first and clipping results, since my geometry is very small, I am getting clipped images with noise despite selecting a high clear_percent.

I need in clipping the image first and select the clipped image with high clear_percent value. Thanks in advance!

This is the code I am using,

sfilter = data_filter.and_filter([

        data_filter.permission_filter(),

        data_filter.date_range_filter('acquired', gte=start_date, lte=end_date),

        data_filter.geometry_filter(geojson_geometry),

        data_filter.asset_filter('ortho_analytic_8b_sr'),

        data_filter.range_filter('clear_percent', gte=80)

    ])

 

    ids = []

    async def main_search():

        async with Session() as sess:

            cl = sess.client('data')

            print("Starting search...")

            items = [i async for i in cl.search(['PSScene'], sfilter, limit=0)]

            print(f'{len(items)} results found for geometry {index}')

 

            for item in items:

                ids.append([item['properties']['acquired'],

                          item['id'],

                          item['properties']['instrument'],

                          item['properties']['cloud_percent'],

                          item['properties']['clear_percent'],

                          item['properties']['clear_confidence_percent'],

                          {'geometry': item['geometry'], 'properties': {}}])

   

    await main_search()

 

    df_ids = gpd.GeoDataFrame(ids, columns = ['time', 'id', 'instrument', 'cloud_percent', 'clear_percent', 'clear_confidence_percent', 'geometry'])

    df_ids['geometry'] = gpd.GeoDataFrame.from_features(df_ids['geometry'])['geometry']

    df_ids = df_ids.set_geometry('geometry')

    df_ids.crs='EPSG:4326'

    #print(df_ids.head())

 

    feature = {'type': 'Feature', 'properties': {}, 'geometry': geojson_geometry}

    # Convert CRS to a projected CRS for accurate area calculations

    footprint = footprint.to_crs('EPSG:3395')  # Example: World Mercator

    df_ids['geometry'] = df_ids['geometry'].to_crs('EPSG:3395')

 

    # Calculate intersection area after CRS conversion

    overlay = df_ids.overlay(footprint, how="intersection")['geometry']

    df_ids['geometry_intersection'] = overlay.area / footprint.to_crs('EPSG:3395').loc[0, 'geometry'].area

 

    # Convert back to geographic CRS if needed

    df_ids = df_ids.to_crs('EPSG:4326')

    footprint = footprint.to_crs('EPSG:4326')

 

    df_ids = df_ids.sort_values(by=['clear_percent', 'cloud_percent'], ascending=[False, True])

    top_image = df_ids.iloc[0]

    print(top_image)

 

    request = order_request.build_request(

        name='test_order',

        products=[

            order_request.product(item_ids=[top_image['id']],

                                  product_bundle='analytic_sr_udm2',

                                  item_type='PSScene')

            ],

        tools=[

            order_request.harmonize_tool(target_sensor='Sentinel-2'),

            order_request.clip_tool(aoi=geojson_geometry)

        ]

    )

 

    #place the request with asynchronous function

    async def main():

        async with Session() as sess:

            cl = sess.client('orders')

            with reporting.StateBar(state='creating') as bar:

                #place order

                order = await cl.create_order(request)

               

                #wait

                bar.update(state='created', order_id=order['id'])

                await cl.wait(order['id'], callback=bar.update_state, max_attempts=0)

           

            #download

            await cl.download_order(order['id'], directory={dir to download}, progress_bar=True)

 

    await main()

icon

Best answer by Miguel Castro Gomez 11 July 2024, 11:35

View original

3 replies

Badge +4

Hi @Hemalatha_V,

The clear_percent filter you are using when running your search checks the pre-computed metadata at scene level.
If you would use the Subscriptions API, there is a cloud_filter tool that would behave in the way you are expecting, deriving cloud cover at the AOI level. 

If you must use Orders API, an alternative would be to download the udm first, run a simple analysis on cloud presence in your AOI, and then trigger the data request depending on the result. 

 

Best, 

Miguel
 

Badge +1

Thank you so much for the reply @Miguel Castro Gomez . Just a quick follow-up question, does downloading just the udm affect the quota?

Best,

Hema.

Badge +4

It should not, but I would highly recommend to make a small test before running anything operational. Additionally, you could check with support@planet.com if you want to make sure how quota is deducted. 

Reply


Planet Monitoring
Investors

© 2024 Planet Labs PBC. All rights reserved.
| Privacy Policy | California Privacy Notice | California Do Not Sell
Your Privacy Choices | Cookie Notice | Terms of Use