rio-tiler 8.0.5__py3-none-any.whl → 9.0.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rio_tiler/io/base.py CHANGED
@@ -362,25 +362,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
362
362
  """Get Asset Reader and options."""
363
363
  return self.reader, {}
364
364
 
365
- def parse_expression(self, expression: str, asset_as_band: bool = False) -> tuple:
366
- """Parse rio-tiler band math expression."""
367
- input_assets = "|".join(self.assets)
368
-
369
- if asset_as_band:
370
- _re = re.compile(rf"\b({input_assets})\b")
371
- else:
372
- _re = re.compile(rf"\b({input_assets})_b\d+\b")
373
-
374
- assets = tuple(set(re.findall(_re, expression)))
375
- if not assets:
376
- raise InvalidExpression(
377
- f"Could not find any valid assets in '{expression}' expression. Assets are: {self.assets}"
378
- if asset_as_band
379
- else f"Could not find any valid assets in '{expression}' expression, maybe try with `asset_as_band=True`. Assets are: {self.assets}"
380
- )
381
-
382
- return assets
383
-
384
365
  def _update_statistics(
385
366
  self,
386
367
  img: ImageData,
@@ -422,31 +403,24 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
422
403
 
423
404
  def _reader(asset: str, **kwargs: Any) -> dict:
424
405
  asset_info = self._get_asset_info(asset)
425
- reader, options = self._get_reader(asset_info)
406
+ reader, reader_options = self._get_reader(asset_info)
426
407
 
408
+ options = {**self.reader_options, **reader_options}
427
409
  with self.ctx(**asset_info.get("env", {})):
428
- with reader(
429
- asset_info["url"],
430
- tms=self.tms,
431
- **{**self.reader_options, **options},
432
- ) as src:
433
- return src.info()
410
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
411
+ return src.info(**asset_info["method_options"])
434
412
 
435
413
  return multi_values(assets, _reader, **kwargs)
436
414
 
437
415
  def statistics(
438
416
  self,
439
417
  assets: Sequence[str] | str | None = None,
440
- asset_indexes: dict[str, Indexes] | None = None,
441
- asset_expression: dict[str, str] | None = None,
442
418
  **kwargs: Any,
443
419
  ) -> dict[str, dict[str, BandStatistics]]:
444
420
  """Return array statistics for multiple assets.
445
421
 
446
422
  Args:
447
423
  assets (sequence of str or str): assets to fetch info from.
448
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
449
- asset_expression (dict, optional): rio-tiler expression for each asset (e.g. {"asset1": "b1/b2+b3", "asset2": ...}).
450
424
  kwargs (optional): Options to forward to the `self.reader.statistics` method.
451
425
 
452
426
  Returns:
@@ -460,25 +434,16 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
460
434
  )
461
435
 
462
436
  assets = cast_to_sequence(assets or self.assets)
463
- asset_indexes = asset_indexes or {}
464
- asset_expression = asset_expression or {}
465
437
 
466
438
  def _reader(asset: str, *args: Any, **kwargs: Any) -> dict:
467
439
  asset_info = self._get_asset_info(asset)
468
- reader, options = self._get_reader(asset_info)
440
+ reader, reader_options = self._get_reader(asset_info)
469
441
 
442
+ options = {**self.reader_options, **reader_options}
470
443
  with self.ctx(**asset_info.get("env", {})):
471
- with reader(
472
- asset_info["url"],
473
- tms=self.tms,
474
- **{**self.reader_options, **options},
475
- ) as src:
476
- return src.statistics(
477
- *args,
478
- indexes=asset_indexes.get(asset, kwargs.pop("indexes", None)),
479
- expression=asset_expression.get(asset),
480
- **kwargs,
481
- )
444
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
445
+ method_options = {**asset_info["method_options"], **kwargs}
446
+ return src.statistics(*args, **method_options)
482
447
 
483
448
  return multi_values(assets, _reader, **kwargs)
484
449
 
@@ -486,7 +451,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
486
451
  self,
487
452
  assets: Sequence[str] | str | None = None,
488
453
  expression: str | None = None,
489
- asset_indexes: dict[str, Indexes] | None = None,
490
454
  categorical: bool = False,
491
455
  categories: list[float] | None = None,
492
456
  percentiles: list[int] | None = None,
@@ -498,8 +462,7 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
498
462
 
499
463
  Args:
500
464
  assets (sequence of str or str): assets to fetch info from.
501
- expression (str, optional): rio-tiler expression for the asset list (e.g. asset1/asset2+asset3).
502
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
465
+ expression (str, optional): rio-tiler expression (e.g. b1/b2+b3).
503
466
  categorical (bool): treat input data as categorical data. Defaults to False.
504
467
  categories (list of numbers, optional): list of categories to return value for.
505
468
  percentiles (list of numbers, optional): list of percentile values to calculate. Defaults to `[2, 98]`.
@@ -512,18 +475,16 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
512
475
  Dict[str, rio_tiler.models.BandStatistics]: bands statistics.
513
476
 
514
477
  """
515
- if not expression:
516
- if not assets:
517
- warnings.warn(
518
- "No `assets` option passed, will fetch statistics for all available assets.",
519
- UserWarning,
520
- )
521
- assets = cast_to_sequence(assets or self.assets)
478
+ if not assets:
479
+ warnings.warn(
480
+ "No `assets` option passed, will fetch statistics for all available assets.",
481
+ UserWarning,
482
+ )
483
+ assets = cast_to_sequence(assets or self.assets)
522
484
 
523
485
  data = self.preview(
524
486
  assets=assets,
525
487
  expression=expression,
526
- asset_indexes=asset_indexes,
527
488
  max_size=max_size,
528
489
  **kwargs,
529
490
  )
@@ -541,7 +502,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
541
502
  tile_z: int,
542
503
  assets: Sequence[str] | str | None = None,
543
504
  expression: str | None = None,
544
- asset_indexes: dict[str, Indexes] | None = None,
545
505
  asset_as_band: bool = False,
546
506
  **kwargs: Any,
547
507
  ) -> ImageData:
@@ -552,87 +512,73 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
552
512
  tile_y (int): Tile's vertical index.
553
513
  tile_z (int): Tile's zoom level index.
554
514
  assets (sequence of str or str, optional): assets to fetch info from.
555
- expression (str, optional): rio-tiler expression for the asset list (e.g. asset1/asset2+asset3).
556
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
515
+ expression (str, optional): rio-tiler expression (e.g. b1/b2+b3).
516
+ asset_as_band (bool, optional): treat each asset as a separate band. Defaults to False.
557
517
  kwargs (optional): Options to forward to the `self.reader.tile` method.
558
518
 
559
519
  Returns:
560
520
  rio_tiler.models.ImageData: ImageData instance with data, mask and tile spatial info.
561
521
 
562
522
  """
523
+ if kwargs.pop("asset_indexes", None):
524
+ warnings.warn(
525
+ "`asset_indexes` parameter is deprecated in `tile` method and will be ignored.",
526
+ DeprecationWarning,
527
+ )
528
+
563
529
  if not self.tile_exists(tile_x, tile_y, tile_z):
564
530
  raise TileOutsideBounds(
565
531
  f"Tile(x={tile_x}, y={tile_y}, z={tile_z}) is outside bounds"
566
532
  )
567
533
 
568
534
  assets = cast_to_sequence(assets)
569
- if assets and expression:
570
- warnings.warn(
571
- "Both expression and assets passed; expression will overwrite assets parameter.",
572
- ExpressionMixingWarning,
573
- )
574
-
575
- if expression:
576
- assets = self.parse_expression(expression, asset_as_band=asset_as_band)
577
-
578
535
  if not assets and self.default_assets:
579
536
  warnings.warn(
580
- f"No assets/expression passed, defaults to {self.default_assets}",
537
+ f"No assets passed, defaults to {self.default_assets}",
581
538
  UserWarning,
582
539
  )
583
540
  assets = self.default_assets
584
541
 
585
542
  if not assets:
586
543
  raise MissingAssets(
587
- "assets must be passed via `expression` or `assets` options, or via class-level `default_assets`."
544
+ "No Asset defined by `assets` option or class-level `default_assets`."
588
545
  )
589
546
 
590
- asset_indexes = asset_indexes or {}
591
-
592
- # We fall back to `indexes` if provided
593
- indexes = kwargs.pop("indexes", None)
594
-
595
547
  def _reader(asset: str, *args: Any, **kwargs: Any) -> ImageData:
596
- idx = asset_indexes.get(asset) or indexes
597
-
598
548
  asset_info = self._get_asset_info(asset)
599
- reader, options = self._get_reader(asset_info)
549
+ asset_name = asset_info["name"]
550
+ reader, reader_options = self._get_reader(asset_info)
600
551
 
552
+ options = {**self.reader_options, **reader_options}
601
553
  with self.ctx(**asset_info.get("env", {})):
602
- with reader(
603
- asset_info["url"],
604
- tms=self.tms,
605
- **{**self.reader_options, **options},
606
- ) as src:
607
- data = src.tile(*args, indexes=idx, **kwargs)
554
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
555
+ method_options = {**asset_info["method_options"], **kwargs}
556
+ data = src.tile(*args, **method_options)
608
557
 
609
558
  self._update_statistics(
610
- data,
611
- indexes=idx,
612
- statistics=asset_info.get("dataset_statistics"),
559
+ data, statistics=asset_info.get("dataset_statistics")
613
560
  )
614
561
 
615
562
  metadata = data.metadata or {}
616
563
  if m := asset_info.get("metadata"):
617
564
  metadata.update(m)
565
+ data.metadata = {asset_name: metadata}
618
566
  data.metadata = {asset: metadata}
619
567
 
568
+ data.band_descriptions = [
569
+ f"{asset_name}_{n}" for n in data.band_descriptions
570
+ ]
620
571
  if asset_as_band:
621
572
  if len(data.band_names) > 1:
622
573
  raise AssetAsBandError(
623
574
  "Can't use `asset_as_band` for multibands asset"
624
575
  )
625
- data.band_names = [asset]
626
- data.band_descriptions = [asset]
627
- else:
628
- data.band_names = [f"{asset}_{n}" for n in data.band_names]
629
- data.band_descriptions = [
630
- f"{asset}_{n}" for n in data.band_descriptions
631
- ]
576
+ data.band_descriptions = [asset_name]
632
577
 
633
578
  return data
634
579
 
635
580
  img = multi_arrays(assets, _reader, tile_x, tile_y, tile_z, **kwargs)
581
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
636
582
  if expression:
637
583
  return img.apply_expression(expression)
638
584
 
@@ -643,7 +589,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
643
589
  bbox: BBox,
644
590
  assets: Sequence[str] | str | None = None,
645
591
  expression: str | None = None,
646
- asset_indexes: dict[str, Indexes] | None = None,
647
592
  asset_as_band: bool = False,
648
593
  **kwargs: Any,
649
594
  ) -> ImageData:
@@ -652,24 +597,21 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
652
597
  Args:
653
598
  bbox (tuple): Output bounds (left, bottom, right, top) in target crs.
654
599
  assets (sequence of str or str, optional): assets to fetch info from.
655
- expression (str, optional): rio-tiler expression for the asset list (e.g. asset1/asset2+asset3).
656
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
600
+ expression (str, optional): rio-tiler expression (e.g. b1/b2+b3).
601
+ asset_as_band (bool, optional): treat each asset as a separate band. Defaults to False.
657
602
  kwargs (optional): Options to forward to the `self.reader.part` method.
658
603
 
659
604
  Returns:
660
605
  rio_tiler.models.ImageData: ImageData instance with data, mask and tile spatial info.
661
606
 
662
607
  """
663
- assets = cast_to_sequence(assets)
664
- if assets and expression:
608
+ if kwargs.pop("asset_indexes", None):
665
609
  warnings.warn(
666
- "Both expression and assets passed; expression will overwrite assets parameter.",
667
- ExpressionMixingWarning,
610
+ "`asset_indexes` parameter is deprecated in `tile` method and will be ignored.",
611
+ DeprecationWarning,
668
612
  )
669
613
 
670
- if expression:
671
- assets = self.parse_expression(expression, asset_as_band=asset_as_band)
672
-
614
+ assets = cast_to_sequence(assets)
673
615
  if not assets and self.default_assets:
674
616
  warnings.warn(
675
617
  f"No assets/expression passed, defaults to {self.default_assets}",
@@ -679,55 +621,44 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
679
621
 
680
622
  if not assets:
681
623
  raise MissingAssets(
682
- "assets must be passed via `expression` or `assets` options, or via class-level `default_assets`."
624
+ "No Asset defined by `assets` option or class-level `default_assets`."
683
625
  )
684
626
 
685
- asset_indexes = asset_indexes or {}
686
-
687
- # We fall back to `indexes` if provided
688
- indexes = kwargs.pop("indexes", None)
689
-
690
627
  def _reader(asset: str, *args: Any, **kwargs: Any) -> ImageData:
691
- idx = asset_indexes.get(asset) or indexes
692
-
693
628
  asset_info = self._get_asset_info(asset)
694
- reader, options = self._get_reader(asset_info)
629
+ asset_name = asset_info["name"]
630
+ reader, reader_options = self._get_reader(asset_info)
695
631
 
632
+ options = {**self.reader_options, **reader_options}
696
633
  with self.ctx(**asset_info.get("env", {})):
697
- with reader(
698
- asset_info["url"],
699
- tms=self.tms,
700
- **{**self.reader_options, **options},
701
- ) as src:
702
- data = src.part(*args, indexes=idx, **kwargs)
634
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
635
+ method_options = {**asset_info["method_options"], **kwargs}
636
+ data = src.part(*args, **method_options)
703
637
 
704
638
  self._update_statistics(
705
639
  data,
706
- indexes=idx,
707
640
  statistics=asset_info.get("dataset_statistics"),
708
641
  )
709
642
 
710
643
  metadata = data.metadata or {}
711
644
  if m := asset_info.get("metadata"):
712
645
  metadata.update(m)
713
- data.metadata = {asset: metadata}
646
+ data.metadata = {asset_name: metadata}
714
647
 
648
+ data.band_descriptions = [
649
+ f"{asset_name}_{n}" for n in data.band_descriptions
650
+ ]
715
651
  if asset_as_band:
716
652
  if len(data.band_names) > 1:
717
653
  raise AssetAsBandError(
718
654
  "Can't use `asset_as_band` for multibands asset"
719
655
  )
720
- data.band_names = [asset]
721
- data.band_descriptions = [asset]
722
- else:
723
- data.band_names = [f"{asset}_{n}" for n in data.band_names]
724
- data.band_descriptions = [
725
- f"{asset}_{n}" for n in data.band_descriptions
726
- ]
656
+ data.band_descriptions = [asset_name]
727
657
 
728
658
  return data
729
659
 
730
660
  img = multi_arrays(assets, _reader, bbox, **kwargs)
661
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
731
662
  if expression:
732
663
  return img.apply_expression(expression)
733
664
 
@@ -737,7 +668,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
737
668
  self,
738
669
  assets: Sequence[str] | str | None = None,
739
670
  expression: str | None = None,
740
- asset_indexes: dict[str, Indexes] | None = None,
741
671
  asset_as_band: bool = False,
742
672
  **kwargs: Any,
743
673
  ) -> ImageData:
@@ -745,82 +675,68 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
745
675
 
746
676
  Args:
747
677
  assets (sequence of str or str, optional): assets to fetch info from.
748
- expression (str, optional): rio-tiler expression for the asset list (e.g. asset1/asset2+asset3).
749
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
678
+ expression (str, optional): rio-tiler expression (e.g. b1/b2+b3).
679
+ asset_as_band (bool, optional): treat each asset as a separate band. Defaults to False.
750
680
  kwargs (optional): Options to forward to the `self.reader.preview` method.
751
681
 
752
682
  Returns:
753
683
  rio_tiler.models.ImageData: ImageData instance with data, mask and tile spatial info.
754
684
 
755
685
  """
756
- assets = cast_to_sequence(assets)
757
- if assets and expression:
686
+ if kwargs.pop("asset_indexes", None):
758
687
  warnings.warn(
759
- "Both expression and assets passed; expression will overwrite assets parameter.",
760
- ExpressionMixingWarning,
688
+ "`asset_indexes` parameter is deprecated in `tile` method and will be ignored.",
689
+ DeprecationWarning,
761
690
  )
762
691
 
763
- if expression:
764
- assets = self.parse_expression(expression, asset_as_band=asset_as_band)
765
-
692
+ assets = cast_to_sequence(assets)
766
693
  if not assets and self.default_assets:
767
694
  warnings.warn(
768
- f"No assets/expression passed, defaults to {self.default_assets}",
695
+ f"No assets passed, defaults to {self.default_assets}",
769
696
  UserWarning,
770
697
  )
771
698
  assets = self.default_assets
772
699
 
773
700
  if not assets:
774
701
  raise MissingAssets(
775
- "assets must be passed via `expression` or `assets` options, or via class-level `default_assets`."
702
+ "No Asset defined by `assets` option or class-level `default_assets`."
776
703
  )
777
704
 
778
- asset_indexes = asset_indexes or {}
779
-
780
- # We fall back to `indexes` if provided
781
- indexes = kwargs.pop("indexes", None)
782
-
783
705
  def _reader(asset: str, **kwargs: Any) -> ImageData:
784
- idx = asset_indexes.get(asset) or indexes
785
-
786
706
  asset_info = self._get_asset_info(asset)
787
- reader, options = self._get_reader(asset_info)
707
+ asset_name = asset_info["name"]
708
+ reader, reader_options = self._get_reader(asset_info)
788
709
 
710
+ options = {**self.reader_options, **reader_options}
789
711
  with self.ctx(**asset_info.get("env", {})):
790
- with reader(
791
- asset_info["url"],
792
- tms=self.tms,
793
- **{**self.reader_options, **options},
794
- ) as src:
795
- data = src.preview(indexes=idx, **kwargs)
712
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
713
+ method_options = {**asset_info["method_options"], **kwargs}
714
+ data = src.preview(**method_options)
796
715
 
797
716
  self._update_statistics(
798
717
  data,
799
- indexes=idx,
800
718
  statistics=asset_info.get("dataset_statistics"),
801
719
  )
802
720
 
803
721
  metadata = data.metadata or {}
804
722
  if m := asset_info.get("metadata"):
805
723
  metadata.update(m)
806
- data.metadata = {asset: metadata}
724
+ data.metadata = {asset_name: metadata}
807
725
 
726
+ data.band_descriptions = [
727
+ f"{asset_name}_{n}" for n in data.band_descriptions
728
+ ]
808
729
  if asset_as_band:
809
730
  if len(data.band_names) > 1:
810
731
  raise AssetAsBandError(
811
732
  "Can't use `asset_as_band` for multibands asset"
812
733
  )
813
- data.band_names = [asset]
814
- data.band_descriptions = [asset]
815
- else:
816
- data.band_names = [f"{asset}_{n}" for n in data.band_names]
817
- data.band_descriptions = [
818
- f"{asset}_{n}" for n in data.band_descriptions
819
- ]
734
+ data.band_descriptions = [asset_name]
820
735
 
821
736
  return data
822
737
 
823
738
  img = multi_arrays(assets, _reader, **kwargs)
739
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
824
740
  if expression:
825
741
  return img.apply_expression(expression)
826
742
 
@@ -832,7 +748,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
832
748
  lat: float,
833
749
  assets: Sequence[str] | str | None = None,
834
750
  expression: str | None = None,
835
- asset_indexes: dict[str, Indexes] | None = None,
836
751
  asset_as_band: bool = False,
837
752
  **kwargs: Any,
838
753
  ) -> PointData:
@@ -842,76 +757,63 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
842
757
  lon (float): Longitude.
843
758
  lat (float): Latitude.
844
759
  assets (sequence of str or str, optional): assets to fetch info from.
845
- expression (str, optional): rio-tiler expression for the asset list (e.g. asset1/asset2+asset3).
846
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
760
+ expression (str, optional): rio-tiler expression (e.g. b1/b2+b3).
761
+ asset_as_band (bool, optional): treat each asset as a separate band. Defaults to False.
847
762
  kwargs (optional): Options to forward to the `self.reader.point` method.
848
763
 
849
764
  Returns:
850
765
  PointData
851
766
 
852
767
  """
853
- assets = cast_to_sequence(assets)
854
- if assets and expression:
768
+ if kwargs.pop("asset_indexes", None):
855
769
  warnings.warn(
856
- "Both expression and assets passed; expression will overwrite assets parameter.",
857
- ExpressionMixingWarning,
770
+ "`asset_indexes` parameter is deprecated in `tile` method and will be ignored.",
771
+ DeprecationWarning,
858
772
  )
859
773
 
860
- if expression:
861
- assets = self.parse_expression(expression, asset_as_band=asset_as_band)
862
-
774
+ assets = cast_to_sequence(assets)
863
775
  if not assets and self.default_assets:
864
776
  warnings.warn(
865
- f"No assets/expression passed, defaults to {self.default_assets}",
777
+ f"No assets passed, defaults to {self.default_assets}",
866
778
  UserWarning,
867
779
  )
868
780
  assets = self.default_assets
869
781
 
870
782
  if not assets:
871
783
  raise MissingAssets(
872
- "assets must be passed via `expression` or `assets` options, or via class-level `default_assets`."
784
+ "No Asset defined by `assets` option or class-level `default_assets`."
873
785
  )
874
786
 
875
- asset_indexes = asset_indexes or {}
876
-
877
- # We fall back to `indexes` if provided
878
- indexes = kwargs.pop("indexes", None)
879
-
880
787
  def _reader(asset: str, *args: Any, **kwargs: Any) -> PointData:
881
- idx = asset_indexes.get(asset) or indexes
882
-
883
788
  asset_info = self._get_asset_info(asset)
884
- reader, options = self._get_reader(asset_info)
789
+ asset_name = asset_info["name"]
790
+ reader, reader_options = self._get_reader(asset_info)
885
791
 
792
+ options = {**self.reader_options, **reader_options}
886
793
  with self.ctx(**asset_info.get("env", {})):
887
- with reader(
888
- asset_info["url"],
889
- tms=self.tms,
890
- **{**self.reader_options, **options},
891
- ) as src:
892
- data = src.point(*args, indexes=idx, **kwargs)
794
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
795
+ method_options = {**asset_info["method_options"], **kwargs}
796
+ data = src.point(*args, **method_options)
893
797
 
894
798
  metadata = data.metadata or {}
895
799
  if m := asset_info.get("metadata"):
896
800
  metadata.update(m)
897
- data.metadata = {asset: metadata}
801
+ data.metadata = {asset_name: metadata}
898
802
 
803
+ data.band_descriptions = [
804
+ f"{asset_name}_{n}" for n in data.band_descriptions
805
+ ]
899
806
  if asset_as_band:
900
807
  if len(data.band_names) > 1:
901
808
  raise AssetAsBandError(
902
809
  "Can't use `asset_as_band` for multibands asset"
903
810
  )
904
- data.band_names = [asset]
905
- data.band_descriptions = [asset]
906
- else:
907
- data.band_names = [f"{asset}_{n}" for n in data.band_names]
908
- data.band_descriptions = [
909
- f"{asset}_{n}" for n in data.band_descriptions
910
- ]
811
+ data.band_descriptions = [asset_name]
911
812
 
912
813
  return data
913
814
 
914
815
  data = multi_points(assets, _reader, lon, lat, **kwargs)
816
+ data.band_names = [f"b{ix + 1}" for ix in range(data.count)]
915
817
  if expression:
916
818
  return data.apply_expression(expression)
917
819
 
@@ -922,7 +824,6 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
922
824
  shape: dict,
923
825
  assets: Sequence[str] | str | None = None,
924
826
  expression: str | None = None,
925
- asset_indexes: dict[str, Indexes] | None = None,
926
827
  asset_as_band: bool = False,
927
828
  **kwargs: Any,
928
829
  ) -> ImageData:
@@ -931,24 +832,21 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
931
832
  Args:
932
833
  shape (dict): Valid GeoJSON feature.
933
834
  assets (sequence of str or str, optional): assets to fetch info from.
934
- expression (str, optional): rio-tiler expression for the asset list (e.g. asset1/asset2+asset3).
935
- asset_indexes (dict, optional): Band indexes for each asset (e.g {"asset1": 1, "asset2": (1, 2,)}).
835
+ expression (str, optional): rio-tiler expression (e.g. b1/b2+b3).
836
+ asset_as_band (bool, optional): treat each asset as a separate band. Defaults to False.
936
837
  kwargs (optional): Options to forward to the `self.reader.feature` method.
937
838
 
938
839
  Returns:
939
840
  rio_tiler.models.ImageData: ImageData instance with data, mask and tile spatial info.
940
841
 
941
842
  """
942
- assets = cast_to_sequence(assets)
943
- if assets and expression:
843
+ if kwargs.pop("asset_indexes", None):
944
844
  warnings.warn(
945
- "Both expression and assets passed; expression will overwrite assets parameter.",
946
- ExpressionMixingWarning,
845
+ "`asset_indexes` parameter is deprecated in `tile` method and will be ignored.",
846
+ DeprecationWarning,
947
847
  )
948
848
 
949
- if expression:
950
- assets = self.parse_expression(expression, asset_as_band=asset_as_band)
951
-
849
+ assets = cast_to_sequence(assets)
952
850
  if not assets and self.default_assets:
953
851
  warnings.warn(
954
852
  f"No assets/expression passed, defaults to {self.default_assets}",
@@ -958,55 +856,44 @@ class MultiBaseReader(SpatialMixin, metaclass=abc.ABCMeta):
958
856
 
959
857
  if not assets:
960
858
  raise MissingAssets(
961
- "assets must be passed via `expression` or `assets` options, or via class-level `default_assets`."
859
+ "No Asset defined by `assets` option or class-level `default_assets`."
962
860
  )
963
861
 
964
- asset_indexes = asset_indexes or {}
965
-
966
- # We fall back to `indexes` if provided
967
- indexes = kwargs.pop("indexes", None)
968
-
969
862
  def _reader(asset: str, *args: Any, **kwargs: Any) -> ImageData:
970
- idx = asset_indexes.get(asset) or indexes
971
-
972
863
  asset_info = self._get_asset_info(asset)
973
- reader, options = self._get_reader(asset_info)
864
+ asset_name = asset_info["name"]
865
+ reader, reader_options = self._get_reader(asset_info)
974
866
 
867
+ options = {**self.reader_options, **reader_options}
975
868
  with self.ctx(**asset_info.get("env", {})):
976
- with reader(
977
- asset_info["url"],
978
- tms=self.tms,
979
- **{**self.reader_options, **options},
980
- ) as src:
981
- data = src.feature(*args, indexes=idx, **kwargs)
869
+ with reader(asset_info["url"], tms=self.tms, **options) as src:
870
+ method_options = {**asset_info["method_options"], **kwargs}
871
+ data = src.feature(*args, **method_options)
982
872
 
983
873
  self._update_statistics(
984
874
  data,
985
- indexes=idx,
986
875
  statistics=asset_info.get("dataset_statistics"),
987
876
  )
988
877
 
989
878
  metadata = data.metadata or {}
990
879
  if m := asset_info.get("metadata"):
991
880
  metadata.update(m)
992
- data.metadata = {asset: metadata}
881
+ data.metadata = {asset_name: metadata}
993
882
 
883
+ data.band_descriptions = [
884
+ f"{asset_name}_{n}" for n in data.band_descriptions
885
+ ]
994
886
  if asset_as_band:
995
887
  if len(data.band_names) > 1:
996
888
  raise AssetAsBandError(
997
889
  "Can't use `asset_as_band` for multibands asset"
998
890
  )
999
- data.band_names = [asset]
1000
- data.band_descriptions = [asset]
1001
- else:
1002
- data.band_names = [f"{asset}_{n}" for n in data.band_names]
1003
- data.band_descriptions = [
1004
- f"{asset}_{n}" for n in data.band_descriptions
1005
- ]
891
+ data.band_descriptions = [asset_name]
1006
892
 
1007
893
  return data
1008
894
 
1009
895
  img = multi_arrays(assets, _reader, shape, **kwargs)
896
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
1010
897
  if expression:
1011
898
  return img.apply_expression(expression)
1012
899
 
@@ -1040,6 +927,14 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1040
927
  bands: Sequence[str] = attr.ib(init=False)
1041
928
  default_bands: Sequence[str] | None = attr.ib(init=False, default=None)
1042
929
 
930
+ def __attrs_post_init__(self):
931
+ """deprecation warning."""
932
+ warnings.warn(
933
+ "MultiBandReader is deprecated and will be removed in a future release. "
934
+ "Please use MultiBaseReader instead.",
935
+ DeprecationWarning,
936
+ )
937
+
1043
938
  def __enter__(self):
1044
939
  """Support using with Context Managers."""
1045
940
  return self
@@ -1066,6 +961,13 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1066
961
 
1067
962
  return bands
1068
963
 
964
+ def _expression_to_bidx(self, bands: Sequence[str], expression: str) -> str:
965
+ mapexpr = {b: f"b{idx + 1}" for idx, b in enumerate(bands)}
966
+ for b in bands:
967
+ _re = re.compile(rf"\b{b}\b")
968
+ expression = _re.sub(mapexpr[b], expression)
969
+ return expression
970
+
1069
971
  def info(
1070
972
  self,
1071
973
  bands: Sequence[str] | str | None = None,
@@ -1090,11 +992,7 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1090
992
 
1091
993
  def _reader(band: str, **kwargs: Any) -> Info:
1092
994
  url = self._get_band_url(band)
1093
- with self.reader(
1094
- url,
1095
- tms=self.tms,
1096
- **self.reader_options,
1097
- ) as src:
995
+ with self.reader(url, tms=self.tms, **self.reader_options) as src:
1098
996
  return src.info()
1099
997
 
1100
998
  bands_metadata = multi_values(bands, _reader, **kwargs)
@@ -1220,24 +1118,19 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1220
1118
 
1221
1119
  def _reader(band: str, *args: Any, **kwargs: Any) -> ImageData:
1222
1120
  url = self._get_band_url(band)
1223
- with self.reader(
1224
- url,
1225
- tms=self.tms,
1226
- **self.reader_options,
1227
- ) as src:
1121
+ with self.reader(url, tms=self.tms, **self.reader_options) as src:
1228
1122
  data = src.tile(*args, **kwargs)
1229
-
1230
1123
  if data.metadata:
1231
1124
  data.metadata = {band: data.metadata}
1232
1125
 
1233
- # use `band` as name instead of band index
1234
- data.band_names = [band]
1235
-
1126
+ # use `band` as name/description instead of band index
1127
+ data.band_descriptions = [band]
1236
1128
  return data
1237
1129
 
1238
1130
  img = multi_arrays(bands, _reader, tile_x, tile_y, tile_z, **kwargs)
1239
-
1131
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
1240
1132
  if expression:
1133
+ expression = self._expression_to_bidx(img.band_descriptions, expression)
1241
1134
  return img.apply_expression(expression)
1242
1135
 
1243
1136
  return img
@@ -1285,24 +1178,19 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1285
1178
 
1286
1179
  def _reader(band: str, *args: Any, **kwargs: Any) -> ImageData:
1287
1180
  url = self._get_band_url(band)
1288
- with self.reader(
1289
- url,
1290
- tms=self.tms,
1291
- **self.reader_options,
1292
- ) as src:
1181
+ with self.reader(url, tms=self.tms, **self.reader_options) as src:
1293
1182
  data = src.part(*args, **kwargs)
1294
-
1295
1183
  if data.metadata:
1296
1184
  data.metadata = {band: data.metadata}
1297
1185
 
1298
- # use `band` as name instead of band index
1299
- data.band_names = [band]
1300
-
1186
+ # use `band` as name/description instead of band index
1187
+ data.band_descriptions = [band]
1301
1188
  return data
1302
1189
 
1303
1190
  img = multi_arrays(bands, _reader, bbox, **kwargs)
1304
-
1191
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
1305
1192
  if expression:
1193
+ expression = self._expression_to_bidx(img.band_descriptions, expression)
1306
1194
  return img.apply_expression(expression)
1307
1195
 
1308
1196
  return img
@@ -1348,24 +1236,19 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1348
1236
 
1349
1237
  def _reader(band: str, **kwargs: Any) -> ImageData:
1350
1238
  url = self._get_band_url(band)
1351
- with self.reader(
1352
- url,
1353
- tms=self.tms,
1354
- **self.reader_options,
1355
- ) as src:
1239
+ with self.reader(url, tms=self.tms, **self.reader_options) as src:
1356
1240
  data = src.preview(**kwargs)
1357
-
1358
1241
  if data.metadata:
1359
1242
  data.metadata = {band: data.metadata}
1360
1243
 
1361
- # use `band` as name instead of band index
1362
- data.band_names = [band]
1363
-
1244
+ # use `band` as name/description instead of band index
1245
+ data.band_descriptions = [band]
1364
1246
  return data
1365
1247
 
1366
1248
  img = multi_arrays(bands, _reader, **kwargs)
1367
-
1249
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
1368
1250
  if expression:
1251
+ expression = self._expression_to_bidx(img.band_descriptions, expression)
1369
1252
  return img.apply_expression(expression)
1370
1253
 
1371
1254
  return img
@@ -1415,23 +1298,19 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1415
1298
 
1416
1299
  def _reader(band: str, *args: Any, **kwargs: Any) -> PointData:
1417
1300
  url = self._get_band_url(band)
1418
- with self.reader(
1419
- url,
1420
- tms=self.tms,
1421
- **self.reader_options,
1422
- ) as src:
1301
+ with self.reader(url, tms=self.tms, **self.reader_options) as src:
1423
1302
  data = src.point(*args, **kwargs)
1424
-
1425
1303
  if data.metadata:
1426
1304
  data.metadata = {band: data.metadata}
1427
1305
 
1428
- # use `band` as name instead of band index
1429
- data.band_names = [band]
1430
-
1306
+ # use `band` as name/description instead of band index
1307
+ data.band_descriptions = [band]
1431
1308
  return data
1432
1309
 
1433
1310
  data = multi_points(bands, _reader, lon, lat, **kwargs)
1311
+ data.band_names = [f"b{ix + 1}" for ix in range(data.count)]
1434
1312
  if expression:
1313
+ expression = self._expression_to_bidx(data.band_descriptions, expression)
1435
1314
  return data.apply_expression(expression)
1436
1315
 
1437
1316
  return data
@@ -1479,24 +1358,19 @@ class MultiBandReader(SpatialMixin, metaclass=abc.ABCMeta):
1479
1358
 
1480
1359
  def _reader(band: str, *args: Any, **kwargs: Any) -> ImageData:
1481
1360
  url = self._get_band_url(band)
1482
- with self.reader(
1483
- url,
1484
- tms=self.tms,
1485
- **self.reader_options,
1486
- ) as src:
1361
+ with self.reader(url, tms=self.tms, **self.reader_options) as src:
1487
1362
  data = src.feature(*args, **kwargs)
1488
-
1489
1363
  if data.metadata:
1490
1364
  data.metadata = {band: data.metadata}
1491
1365
 
1492
- # use `band` as name instead of band index
1493
- data.band_names = [band]
1494
-
1366
+ # use `band` as name/description instead of band index
1367
+ data.band_descriptions = [band]
1495
1368
  return data
1496
1369
 
1497
1370
  img = multi_arrays(bands, _reader, shape, **kwargs)
1498
-
1371
+ img.band_names = [f"b{ix + 1}" for ix in range(img.count)]
1499
1372
  if expression:
1373
+ expression = self._expression_to_bidx(img.band_descriptions, expression)
1500
1374
  return img.apply_expression(expression)
1501
1375
 
1502
1376
  return img