1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 """
30 This module defines filters and filter expressions for EO Coverages.
31 For more information on filters, see :mod:`eoxserver.core.filters`.
32 """
33
34 import math
35 from datetime import datetime
36
37 from django.db.models import Q, Count
38 from django.contrib.gis.geos import (
39 fromstr as geos_fromstr, Polygon
40 )
41 from django.contrib.gis.gdal import SpatialReference
42
43 from eoxserver.core.system import System
44 from eoxserver.core.registry import FactoryInterface
45 from eoxserver.core.filters import (
46 FilterExpressionInterface, FilterInterface, SimpleExpression,
47 SimpleExpressionFactory
48 )
49 from eoxserver.core.util.timetools import UTCOffsetTimeZoneInfo
50 from eoxserver.core.exceptions import (
51 InternalError, InvalidExpressionError, UnknownAttribute
52 )
53 from eoxserver.backends.base import LocationWrapper
54 from eoxserver.resources.coverages.models import EOMetadataRecord
55 from eoxserver.resources.coverages.wrappers import (
56 RectifiedDatasetWrapper, ReferenceableDatasetWrapper,
57 RectifiedStitchedMosaicWrapper, DatasetSeriesWrapper
58 )
59
60
61
62
63
64 -class Slice(object):
65 """
66 This class contains information about a slice subsetting. The
67 constructor accepts three arguments:
68
69 * ``crs_id``: either ``"imageCRS"`` or an integer EPSG SRID,
70 * ``axis_label``: the axis label the slicing operation refers to,
71 * ``slice_point``: a :class:`float` or :class:`int` containing the
72 slice point information
73
74 :exc:`~.InternalError` is raised if arguments do not validate.
75 """
76 - def __init__(self, crs_id, axis_label, slice_point):
82
83 - def __validate(self, crs_id, axis_label, slice_point):
94
95
96 @property
99
100
101 @property
103 return self.__axis_label
104
105
106 @property
108 return self.__slice_point
109
111 """
112 This class contains information about a bounded area. The
113 constructor accepts a ``crs_id`` and four bounds arguments
114 ``minx, miny, maxx, maxy``. The ``crs_id`` parameter may be set to
115 ``"imageCRS"`` or an integer EPSG SRID. The bounds parameters may
116 be set to a :class:`float` or :class:`int` value designating the
117 bound in the given coordinate system or to ``"unbounded"``.
118
119 :exc:`~.InternalError` is raised if the arguments do not validate.
120 :exc:`~.InvalidExpressionError` is raised if the lower bounds of
121 an axis are greater than the upper bounds.
122 """
123 - def __init__(self, crs_id, minx, miny, maxx, maxy):
131
132 - def __validate(self, crs_id, minx, miny, maxx, maxy):
133 if not (crs_id == "imageCRS" or isinstance(crs_id, int)):
134 raise InternalError(
135 "'crs_id' must be set to 'imageCRS' or to an integer."
136 )
137
138 for bound in (minx, miny, maxx, maxy):
139 if not (bound == "unbounded" or isinstance(bound, float) or\
140 isinstance(bound, int)):
141 raise InternalError(
142 "Bounds must be set to 'unbounded', float or int."
143 )
144
145 if (not (minx == "unbounded" or maxx == "unbounded") and minx > maxx) or\
146 (not (miny == "unbounded" or maxy == "unbounded") and miny > maxy):
147 raise InvalidExpressionError(
148 "Invalid bounds: lower bound greater than upper bound."
149 )
150
151
152 @property
155
156
157 @property
160
161
162 @property
165
166
167 @property
170
171
172 @property
175
177 """
178 This class contains information about a time interval. The
179 constructor accepts two arguments: ``begin`` and ``end`` which
180 must be set either to the string ``"unbounded"`` or a
181 :class:`datetime.datetime` object.
182
183 :exc:`~.InternalError` is raised if the arguments do not validate.
184 :exc:`~.InvalidExpressionError` is raised if the begin time is
185 later than the end time.
186 """
187
193
195 for timestamp in (begin, end):
196 if not (timestamp == "unbounded" or isinstance(timestamp, datetime)):
197 raise InternalError(
198 "Time bound must be 'unbounded' or 'datetime.datetime' object."
199 )
200
201 if not (begin == "unbounded" or end == "unbounded") and end < begin:
202 raise InvalidExpressionError(
203 "Begin of time interval later than end."
204 )
205
206 @property
209
210 @property
213
219 """
220 Filter expression implementation representing an attribute lookup
221 on a model. Expects three operands:
222
223 * the attribute name; the possible names are defined separately for
224 each resource class;
225 * the matching operation; the range of applicable operations
226 comprises the field lookups defined by Django; the 'search',
227 'regex' and 'iregex' operations are not supported because they are
228 database dependent; the shortcuts "=", "<", "<=", ">=", ">" are
229 allowed;
230 * the search value; has to be convertible to the type of the
231 attribute
232 """
233 REGISTRY_CONF = {
234 "name": "Attribute Lookup Expression",
235 "impl_id": "resources.coverages.filters.AttributeExpression",
236 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
237 }
238
239 OP_NAME = "attr"
240 NUM_OPS = 3
241
242 LOOKUPS = (
243 "=", "exact", "iexact", "contains", "icontains", "in", ">" ,
244 "gt", ">=", "gte", "<", "lt", "<=", "lte", "startswith",
245 "istartswith", "endswith", "iendswith", "range", "year",
246 "month", "day", "weekday", "isnull"
247 )
248
249
258
259 AttributeExpressionImplementation = \
260 FilterExpressionInterface.implement(AttributeExpression)
263 """
264 Filter expression implementation representing a time slice. Expects
265 one operand: a :class:`datetime.datetime` object representing the
266 slice point in time.
267 """
268 REGISTRY_CONF = {
269 "name": "Time Slice Expression",
270 "impl_id": "resources.coverages.filters.TimeSliceExpression",
271 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
272 }
273
274 OP_NAME = "time_slice"
275 NUM_OPS = 1
276
278 super(TimeSliceExpression, self)._validateOperands(operands)
279
280 if not isinstance(operands[0], datetime):
281 raise InternalError(
282 "Expected 'datetime.datetime' object as operand, got '%s' object." % operands[0].__class__.__name__
283 )
284
285 TimeSliceExpressionImplementation = \
286 FilterExpressionInterface.implement(TimeSliceExpression)
289 """
290 Filter expression implementation representing a time interval.
291 It expects one operand of type :class:`TimeInterval`.
292 """
293 NUM_OPS = 1
294
302
304 """
305 Filter expression implementation that matches if a time or
306 time interval intersects with the time interval specified in the
307 expression. Inherits from :class:`TimeIntervalExpression`.
308 """
309 REGISTRY_CONF = {
310 "name": "Intersecting Time Interval Expression",
311 "impl_id": "resources.coverages.filters.IntersectingTimeIntervalExpression",
312 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
313 }
314
315 OP_NAME = "time_intersects"
316
317 IntersectingTimeIntervalExpressionImplementation = \
318 FilterExpressionInterface.implement(IntersectingTimeIntervalExpression)
321 """
322 Filter expression implementation that matches if a time or time
323 interval is contained in the time interval specified in the
324 expression. Inherits from :class:`TimeIntervalExpression`.
325 """
326 REGISTRY_CONF = {
327 "name": "Containing Time Interval Expression",
328 "impl_id": "resources.coverages.filters.ContainingTimeIntervalExpression",
329 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
330 }
331
332 OP_NAME = "time_within"
333
334 ContainingTimeIntervalExpressionImplementation = \
335 FilterExpressionInterface.implement(ContainingTimeIntervalExpression)
338 """
339 Filter expression implementation that represents a slice subsetting.
340 It expects one operand of type :class:`Slice`.
341 """
342 REGISTRY_CONF = {
343 "name": "Spatial Slice Expression",
344 "impl_id": "resources.coverages.filters.SpatialSliceExpression",
345 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
346 }
347
348 OP_NAME = "spatial_slice"
349 NUM_OPS = 1
350
359
360 SpatialSliceExpressionImplementation = \
361 FilterExpressionInterface.implement(SpatialSliceExpression)
364 """
365 Filter expression implementation that represents a trim or BBOX
366 subsetting. It expects one operand of type :class:`BoundedArea`.
367 """
368 NUM_OPS = 1
369
378
392
393 FootprintIntersectsAreaExpressionImplementation = \
394 FilterExpressionInterface.implement(FootprintIntersectsAreaExpression)
409
410 FootprintWithinAreaExpressionImplementation = \
411 FilterExpressionInterface.implement(FootprintWithinAreaExpression)
414 """
415 Filter expression referring to the coverages contained in a
416 container object (StitchedMosaic or DatasetSeries). Expects one
417 operand, namely an integer resource ID relating to the container
418 object.
419 """
420 REGISTRY_CONF = {
421 "name": "Contained Coverage Expression",
422 "impl_id": "resources.coverages.filters.ContainedCoverageExpression",
423 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
424 }
425
426 OP_NAME = "contained_in"
427 NUM_OPS = 1
428
437
438 ContainedCoverageExpressionImplementation = \
439 FilterExpressionInterface.implement(ContainedCoverageExpression)
442 """
443 Filter expression referring to the coverages containing a
444 StitchedMosaic or Dataset. Expects one operand, namely an integer resource
445 ID relating to the contained object.
446 """
447 REGISTRY_CONF = {
448 "name": "Contains Coverage Expression",
449 "impl_id": "resources.coverages.filters.ContainsCoverageExpression",
450 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
451 }
452
453 OP_NAME = "contains"
454 NUM_OPS = 1
455
464
465 ContainsCoverageExpressionImplementation = \
466 FilterExpressionInterface.implement(ContainsCoverageExpression)
469 """
470 Filter expression implementation that matches coverages which are
471 not related to any container (StitchedMosaic or DatasetSeries).
472 Takes no operands.
473 """
474
475 REGISTRY_CONF = {
476 "name": "Orphaned Coverage Expression",
477 "impl_id": "resources.coverages.filters.OrphanedCoverageExpression",
478 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
479 }
480
481 OP_NAME = "orphaned"
482 NUM_OPS = 0
483
484 OrphanedCoverageExpressionImplementation = \
485 FilterExpressionInterface.implement(OrphanedCoverageExpression)
489 """
490 Filter expression that matches datasets which are referenced by a location.
491 """
492
493 REGISTRY_CONF = {
494 "name": "Location References Dataset Expression",
495 "impl_id": "resources.coverages.filters.LocationReferencesDatasetExpression",
496 "factory_ids": ("resources.coverages.filters.CoverageExpressionFactory",)
497 }
498
499 OP_NAME = "referenced_by"
500 NUM_OPS = 1
501
510
511 LocationReferencesDatasetExpressionImplementation = \
512 FilterExpressionInterface.implement(LocationReferencesDatasetExpression)
519 """
520 Base class for attribute lookup filters.
521 """
522
523 WRAPPER_CLASS = None
524
527
529 if op == "=":
530 return ""
531 elif op == "<":
532 return "__lt"
533 elif op == "<=":
534 return "__lte"
535 elif op == ">=":
536 return "__gte"
537 elif op == ">":
538 return "__gt"
539 else:
540 return "__%s" % op
541
543 try:
544 if op in ("=", "exact"):
545 return model_value == value
546 elif op == "iexact":
547 return model_value.lower() == value.lower()
548 elif op == "contains":
549 return model_value.find(value) != -1
550 elif op == "icontains":
551 return model_value.lower().find(value.lower()) != -1
552 elif op == "in":
553 return model_value in value
554 elif op in ("<", "lt"):
555 return model_value < value
556 elif op in ("<=", "lte"):
557 return model_value <= value
558 elif op in (">=", "gte"):
559 return model_value >= value
560 elif op in (">", "gt"):
561 return model_value > value
562 elif op == "startswith":
563 return model_value.startswith(value)
564 elif op == "istartswith":
565 return model_value.lower().startswith(value.lower())
566 elif op == "endswith":
567 return model_value.endswith(value)
568 elif op == "iendswith":
569 return model_value.lower().endswith(value.lower())
570 elif op == "range":
571 return value[0] <= model_value and model_value <= value[1]
572 elif op == "year":
573 return model_value.year == value
574 elif op == "month":
575 return model_value.month == value
576 elif op == "day":
577 return model_value.day == value
578 elif op == "weekday":
579 return model_value.weekday() == value
580 elif op == "isnull":
581 if value:
582 return model_value is None
583 else:
584 return model_value is not None
585 except:
586 raise InvalidExpressionError(
587 "Could not apply attribute expression to given attribute."
588 )
589
591 if raw_op.startswith("!"):
592 invert = True
593 op = raw_op.lstrip("!")
594 else:
595 invert = False
596 op = raw_op
597
598 return (invert, op)
599
619
631
633 """
634 Filter that executes attribute lookups on Rectified Datasets.
635 """
636
637 REGISTRY_CONF = {
638 "name": "Attribute Lookup Filter for Rectified Datasets",
639 "impl_id": "resources.coverages.filters.RectifiedDatasetAttribute",
640 "registry_values": {
641 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedDatasetWrapper",
642 "core.filters.expr_class_id": "resources.coverages.filters.AttributeExpression"
643 }
644 }
645
646 WRAPPER_CLASS = RectifiedDatasetWrapper
647
648 RectifiedDatasetAttributeFilterImplementation = \
649 FilterInterface.implement(RectifiedDatasetAttributeFilter)
652 """
653 Filter that executes attribute lookup operations on Referenceable
654 Datasets.
655 """
656
657 REGISTRY_CONF = {
658 "name": "Attribute Lookup Filter for Referenceable Datasets",
659 "impl_id": "resources.coverages.filters.ReferenceableDatasetAttribute",
660 "registry_values": {
661 "core.filters.res_class_id": "resources.coverages.wrappers.ReferenceableDatasetWrapper",
662 "core.filters.expr_class_id": "resources.coverages.filters.AttributeExpression"
663 }
664 }
665
666 WRAPPER_CLASS = ReferenceableDatasetWrapper
667
668 ReferenceableDatasetAttributeFilterImplementation = \
669 FilterInterface.implement(ReferenceableDatasetAttributeFilter)
672 """
673 Filter that executes attribute lookup operations on Rectified
674 Stitched Mosaics.
675 """
676
677 REGISTRY_CONF = {
678 "name": "Attribute Lookup Filter for Rectified Stitched Mosaics",
679 "impl_id": "resources.coverages.filters.RectifiedStitchedMosaicAttribute",
680 "registry_values": {
681 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
682 "core.filters.expr_class_id": "resources.coverages.filters.AttributeExpression"
683 }
684 }
685
686 WRAPPER_CLASS = RectifiedStitchedMosaicWrapper
687
688 RectifiedStitchedMosaicAttributeFilterImplementation = \
689 FilterInterface.implement(RectifiedStitchedMosaicAttributeFilter)
692 """
693 Filter class for time slice operations.
694 """
696 timestamp = expr.getOperands()[0]
697
698 qs = qs.exclude(eo_metadata__timestamp_begin__gt=timestamp)
699 qs = qs.exclude(eo_metadata__timestamp_end__lt=timestamp)
700
701 return qs
702
708
710 """
711 Filter which matches Rectified Datasets whose acquisition time
712 interval contains a given timestamp.
713 """
714 REGISTRY_CONF = {
715 "name": "Time Slice Filter for Rectified Datasets",
716 "impl_id": "resources.coverages.filters.RectifiedDatasetTimeSlice",
717 "registry_values": {
718 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedDatasetWrapper",
719 "core.filters.expr_class_id": "resources.coverages.filters.TimeSliceExpression"
720 }
721 }
722
723 RectifiedDatasetTimeSliceFilterImplementation = \
724 FilterInterface.implement(RectifiedDatasetTimeSliceFilter)
727 """
728 Filter which matches Referenceable Datasets whose acquisition time
729 interval contains a given timestamp.
730 """
731 REGISTRY_CONF = {
732 "name": "Time Slice Filter for Referenceable Datasets",
733 "impl_id": "resources.coverages.filters.ReferenceableDatasetTimeSlice",
734 "registry_values": {
735 "core.filters.res_class_id": "resources.coverages.wrappers.ReferenceableDatasetWrapper",
736 "core.filters.expr_class_id": "resources.coverages.filters.TimeSliceExpression"
737 }
738 }
739
740 ReferenceableDatasetTimeSliceFilterImplementation = \
741 FilterInterface.implement(ReferenceableDatasetTimeSliceFilter)
744 """
745 Filter which matches Rectified Stitched Mosaics whose acquisition
746 time interval contains a given timestamp.
747 """
748 REGISTRY_CONF = {
749 "name": "Time Slice Filter for Rectified Stitched Mosaics",
750 "impl_id": "resources.coverages.filters.RectifiedStitchedMosaicTimeSlice",
751 "registry_values": {
752 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
753 "core.filters.expr_class_id": "resources.coverages.filters.TimeSliceExpression"
754 }
755 }
756
757 RectifiedStitchedMosaicTimeSliceFilterImplementation = \
758 FilterInterface.implement(RectifiedStitchedMosaicTimeSliceFilter)
761 """
762 Filter class for 'time_intersects' operations.
763 """
765 begin = expr.getOperands()[0].begin
766 end = expr.getOperands()[0].end
767
768 if begin == "unbounded":
769 if end == "unbounded":
770 return qs
771 else:
772 return qs.filter(
773 eo_metadata__timestamp_begin__lte=end
774 )
775 else:
776 if end == "unbounded":
777 return qs.filter(
778 eo_metadata__timestamp_end__gte=begin
779 )
780 else:
781 return qs.exclude(
782 eo_metadata__timestamp_begin__gt=end
783 ).exclude(
784 eo_metadata__timestamp_end__lt=begin
785 )
786
801
803 """
804 Filter which matches Rectified Datasets whose acquisition time
805 interval intersects a given time interval.
806 """
807 REGISTRY_CONF = {
808 "name": "Filter for 'time_intersects' operations on Rectified Datasets",
809 "impl_id": "resources.coverages.filters.RectifiedDatasetIntersectingTimeInterval",
810 "registry_values": {
811 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedDatasetWrapper",
812 "core.filters.expr_class_id": "resources.coverages.filters.IntersectingTimeIntervalExpression"
813 }
814 }
815
816 RectifiedDatasetIntersectingTimeIntervalFilterImplementation = \
817 FilterInterface.implement(RectifiedDatasetIntersectingTimeIntervalFilter)
820 """
821 Filter which matches Referenceable Datasets whose acquisition time
822 interval intersects a given time interval.
823 """
824 REGISTRY_CONF = {
825 "name": "Filter for 'time_intersects' operations on Referenceable Datasets",
826 "impl_id": "resources.coverages.filters.ReferenceableDatasetIntersectingTimeInterval",
827 "registry_values": {
828 "core.filters.res_class_id": "resources.coverages.wrappers.ReferenceableDatasetWrapper",
829 "core.filters.expr_class_id": "resources.coverages.filters.IntersectingTimeIntervalExpression"
830 }
831 }
832
833 ReferenceableDatasetIntersectingTimeIntervalFilterImplementation = \
834 FilterInterface.implement(ReferenceableDatasetIntersectingTimeIntervalFilter)
837 """
838 Filter which matches Rectified Stitched Mosaics whose acquisition
839 time interval intersects a given time interval.
840 """
841 REGISTRY_CONF = {
842 "name": "Filter for 'time_intersects' operations on Rectified Stitched Mosaics",
843 "impl_id": "resources.coverages.filters.RectifiedStitchedMosaicIntersectingTimeInterval",
844 "registry_values": {
845 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
846 "core.filters.expr_class_id": "resources.coverages.filters.IntersectingTimeIntervalExpression"
847 }
848 }
849
850 RectifiedStitchedMosaicIntersectingTimeIntervalFilterImplementation = \
851 FilterInterface.implement(RectifiedStitchedMosaicIntersectingTimeIntervalFilter)
854 """
855 Filter class for 'time_within' operations.
856 """
858 begin = expr.getOperands()[0].begin
859 end = expr.getOperands()[0].end
860
861 if begin == "unbounded":
862 if end == "unbounded":
863 return qs
864 else:
865 return qs.filter(
866 eo_metadata__timestamp_end__lte=end
867 )
868 else:
869 if end == "unbounded":
870 return qs.filter(
871 eo_metadata__timestamp_begin__gte=begin
872 )
873 else:
874 return qs.filter(
875 eo_metadata__timestamp_begin__gte=begin,
876 eo_metadata__timestamp_end__lte=end
877 )
878
885
887 """
888 Filter which matches Rectified Datasets whose acquisition time
889 interval is contained within a given time interval.
890 """
891 REGISTRY_CONF = {
892 "name": "Filter for 'time_within' operations on Rectified Datasets",
893 "impl_id": "resources.coverages.filters.RectifiedDatasetContainingTimeInterval",
894 "registry_values": {
895 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedDatasetWrapper",
896 "core.filters.expr_class_id": "resources.coverages.filters.ContainingTimeIntervalExpression"
897 }
898 }
899
900 RectifiedDatasetContainingTimeIntervalFilterImplementation = \
901 FilterInterface.implement(RectifiedDatasetContainingTimeIntervalFilter)
904 """
905 Filter which matches Referenceable Datasets whose acquisition time
906 interval is contained within a given time interval.
907 """
908 REGISTRY_CONF = {
909 "name": "Filter for 'time_within' operations on Referenceable Datasets",
910 "impl_id": "resources.coverages.filters.ReferenceableDatasetContainingTimeInterval",
911 "registry_values": {
912 "core.filters.res_class_id": "resources.coverages.wrappers.ReferenceableDatasetWrapper",
913 "core.filters.expr_class_id": "resources.coverages.filters.ContainingTimeIntervalExpression"
914 }
915 }
916
917 ReferenceableDatasetContainingTimeIntervalFilterImplementation = \
918 FilterInterface.implement(ReferenceableDatasetContainingTimeIntervalFilter)
921 """
922 Filter which matches Rectified Stitched Mosaics whose acquisition
923 time interval is contained within a given time interval.
924 """
925 REGISTRY_CONF = {
926 "name": "Filter for 'time_within' operations on Rectified Stitched Mosaics",
927 "impl_id": "resources.coverages.filters.RectifiedStitchedMosaicContainingTimeInterval",
928 "registry_values": {
929 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
930 "core.filters.expr_class_id": "resources.coverages.filters.ContainingTimeIntervalExpression"
931 }
932 }
933
934 RectifiedStitchedMosaicContainingTimeIntervalFilterImplementation = \
935 FilterInterface.implement(RectifiedStitchedMosaicContainingTimeIntervalFilter)
938 """
939 Common base class for spatial filters.
940 """
941
956
958 srs = self._getSRS(crs_id)
959
960 if srs.geographic:
961 return (-180.0, -90.0, 180.0, 90.0)
962 else:
963 earth_circumference = 2*math.pi*srs.semi_major
964
965 return (
966 -earth_circumference,
967 -earth_circumference,
968 earth_circumference,
969 earth_circumference
970 )
971
973 srs = self._getSRS(crs_id)
974
975 if srs.geographic:
976 return 1e-8
977 else:
978 return 1e-2
979
981 """
982 Common base class for spatial slice filters.
983 """
984
1010
1012 slice = expr.getOperands()[0]
1013
1014 line = self._getLine(slice)
1015
1016
1017
1018
1019
1020 eoqs = EOMetadataRecord.objects.filter(
1021 footprint__intersects=line
1022 )
1023
1024 return qs.filter(
1025 eo_metadata__in=tuple(eoqs.values_list("pk", flat=True))
1026 )
1027
1028
1029
1038
1040 """
1041 Filter which matches Rectified Datasets whose footprint intersects
1042 a given spatial slice.
1043 """
1044 REGISTRY_CONF = {
1045 "name": "Spatial Slice Filter for Rectified Datasets",
1046 "impl_id": "resources.coverages.filters.RectifiedDatasetSpatialSlice",
1047 "registry_values": {
1048 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedDatasetWrapper",
1049 "core.filters.expr_class_id": "resources.coverages.filters.SpatialSliceExpression"
1050 }
1051 }
1052
1054 return "rectifieddatasetrecord_set"
1055
1056 RectifiedDatasetSpatialSliceFilterImplementation = \
1057 FilterInterface.implement(RectifiedDatasetSpatialSliceFilter)
1060 """
1061 Filter which matches Referenceable Datasets whose footprint
1062 intersects a given spatial slice.
1063 """
1064 REGISTRY_CONF = {
1065 "name": "Spatial Slice Filter for Referenceable Datasets",
1066 "impl_id": "resources.coverages.filters.ReferenceableDatasetSpatialSlice",
1067 "registry_values": {
1068 "core.filters.res_class_id": "resources.coverages.wrappers.ReferenceableDatasetWrapper",
1069 "core.filters.expr_class_id": "resources.coverages.filters.SpatialSliceExpression"
1070 }
1071 }
1072
1074 return "referenceabledatasetrecord_set"
1075
1076
1077 ReferenceableDatasetSpatialSliceFilterImplementation = \
1078 FilterInterface.implement(ReferenceableDatasetSpatialSliceFilter)
1081 """
1082 Filter which matches Rectified Stitched Mosaics whose footprint
1083 intersects a given spatial slice.
1084 """
1085
1086 REGISTRY_CONF = {
1087 "name": "Spatial Slice Filter for Rectified Stitched Mosaics",
1088 "impl_id": "resources.coverages.filters.RectifiedStitchedMosaicSpatialSlice",
1089 "registry_values": {
1090 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
1091 "core.filters.expr_class_id": "resources.coverages.filters.SpatialSliceExpression"
1092 }
1093 }
1094
1096 return "rectifiedstitchedmosaicrecord_set"
1097
1099 if axis_label in ("x", "lon", "long", "Long"):
1100 return "extent__size_x"
1101 else:
1102 return "extent__size_y"
1103
1104
1105 RectifiedStitchedMosaicSpatialSliceFilterImplementation = \
1106 FilterInterface.implement(RectifiedStitchedMosaicSpatialSliceFilter)
1153
1184
1212
1229
1230 RectifiedDatasetFootprintIntersectsAreaFilterImplementation = \
1231 FilterInterface.implement(RectifiedDatasetFootprintIntersectsAreaFilter)
1250
1251 RectifiedDatasetFootprintWithinAreaFilterImplementation = \
1252 FilterInterface.implement(RectifiedDatasetFootprintWithinAreaFilter)
1270
1271 ReferenceableDatasetFootprintIntersectsAreaFilterImplementation = \
1272 FilterInterface.implement(ReferenceableDatasetFootprintIntersectsAreaFilter)
1290
1291 ReferenceableDatasetFootprintWithinAreaFilterImplementation = \
1292 FilterInterface.implement(ReferenceableDatasetFootprintWithinAreaFilter)
1310
1311 RectifiedStitchedMosaicFootprintIntersectsAreaFilterImplementation = \
1312 FilterInterface.implement(RectifiedStitchedMosaicFootprintIntersectsAreaFilter)
1331
1332 RectifiedStitchedMosaicFootprintWithinAreaFilterImplementation = \
1333 FilterInterface.implement(RectifiedStitchedMosaicFootprintWithinAreaFilter)
1336 """
1337 Filter which matches RectifiedDatasets contained in a given
1338 RectifiedStitchedMosaic or Dataset series.
1339 """
1340 REGISTRY_CONF = {
1341 "name": "Contained Rectified Dataset Filter",
1342 "impl_id": "resources.coverages.filters.ContainedRectifiedDataset",
1343 "registry_values": {
1344 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedDatasetWrapper",
1345 "core.filters.expr_class_id": "resources.coverages.filters.ContainedCoverageExpression"
1346 }
1347 }
1348
1350 container_id = expr.getOperands()[0]
1351
1352 return qs.filter(
1353 Q(rect_stitched_mosaics__pk=container_id) | \
1354 Q(dataset_series_set__pk=container_id)
1355 )
1356
1361
1362 ContainedRectifiedDatasetFilterImplementation = \
1363 FilterInterface.implement(ContainedRectifiedDatasetFilter)
1366 """
1367 Filter which matches ReferenceableDatasets contained in a given
1368 DatasetSeries.
1369 """
1370 REGISTRY_CONF = {
1371 "name": "Contained Referenceable Dataset Filter",
1372 "impl_id": "resources.coverages.filters.ContainedReferenceableDatasetFilter",
1373 "registry_values": {
1374 "core.filters.res_class_id": "resources.coverages.wrappers.ReferenceableDatasetWrapper",
1375 "core.filters.expr_class_id": "resources.coverages.filters.ContainedCoverageExpression"
1376 }
1377 }
1378
1380 container_id = expr.getOperands()[0]
1381
1382 return qs.filter(dataset_series_set__pk=container_id)
1383
1388
1389 ContainedReferenceableDatasetFilterImplementation = \
1390 FilterInterface.implement(ContainedReferenceableDatasetFilter)
1393 """
1394 Filter which matches RectifiedStitchedMosaics contained in a given
1395 DatasetSeries.
1396 """
1397 REGISTRY_CONF = {
1398 "name": "Contained Referenceable Dataset Filter",
1399 "impl_id": "resources.coverages.filters.ContainedRectifiedStitchedMosaicFilter",
1400 "registry_values": {
1401 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
1402 "core.filters.expr_class_id": "resources.coverages.filters.ContainedCoverageExpression"
1403 }
1404 }
1405
1407 container_id = expr.getOperands()[0]
1408
1409 return qs.filter(dataset_series_set__pk=container_id)
1410
1415
1416 ContainedRectifiedStitchedMosaicFilterImplementation = \
1417 FilterInterface.implement(ContainedRectifiedStitchedMosaicFilter)
1420 """
1421 Filter which matches RectifiedStitchedMosaics which contain the
1422 RectifiedDataset with the resource primary key conveyed with the
1423 expression.
1424 """
1425
1426 REGISTRY_CONF = {
1427 "name": "Filter for 'contains' operations on RectifiedStitchedMosaics",
1428 "impl_id": "resources.coverages.filters.RectifiedStitchedMosaicContains",
1429 "registry_values": {
1430 "core.filters.res_class_id": "resources.coverages.wrappers.RectifiedStitchedMosaicWrapper",
1431 "core.filters.expr_class_id": "resources.coverages.filters.ContainsCoverageExpression"
1432 }
1433 }
1434
1436 res_id = expr.getOperands()[0]
1437
1438 return qs.filter(rect_datasets__pk=res_id)
1439
1444
1445 RectifiedStitchedMosaicContainsFilterImplementation = \
1446 FilterInterface.implement(RectifiedStitchedMosaicContainsFilter)
1449 """
1450 Filter which matches DatasetSeries which contain the (Rectified
1451 or Referenceable) Dataset with the resource primary key conveyed
1452 with the expression.
1453 """
1454
1455