geovisio 2.9.0__py3-none-any.whl → 2.10.0__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.
Files changed (65) hide show
  1. geovisio/__init__.py +6 -1
  2. geovisio/config_app.py +5 -5
  3. geovisio/translations/ar/LC_MESSAGES/messages.mo +0 -0
  4. geovisio/translations/ar/LC_MESSAGES/messages.po +818 -0
  5. geovisio/translations/br/LC_MESSAGES/messages.po +1 -1
  6. geovisio/translations/da/LC_MESSAGES/messages.mo +0 -0
  7. geovisio/translations/da/LC_MESSAGES/messages.po +4 -3
  8. geovisio/translations/de/LC_MESSAGES/messages.mo +0 -0
  9. geovisio/translations/de/LC_MESSAGES/messages.po +55 -2
  10. geovisio/translations/el/LC_MESSAGES/messages.po +1 -1
  11. geovisio/translations/en/LC_MESSAGES/messages.mo +0 -0
  12. geovisio/translations/en/LC_MESSAGES/messages.po +193 -139
  13. geovisio/translations/eo/LC_MESSAGES/messages.mo +0 -0
  14. geovisio/translations/eo/LC_MESSAGES/messages.po +53 -4
  15. geovisio/translations/es/LC_MESSAGES/messages.po +1 -1
  16. geovisio/translations/fi/LC_MESSAGES/messages.po +1 -1
  17. geovisio/translations/fr/LC_MESSAGES/messages.mo +0 -0
  18. geovisio/translations/fr/LC_MESSAGES/messages.po +91 -3
  19. geovisio/translations/hu/LC_MESSAGES/messages.po +1 -1
  20. geovisio/translations/it/LC_MESSAGES/messages.mo +0 -0
  21. geovisio/translations/it/LC_MESSAGES/messages.po +63 -3
  22. geovisio/translations/ja/LC_MESSAGES/messages.po +1 -1
  23. geovisio/translations/ko/LC_MESSAGES/messages.po +1 -1
  24. geovisio/translations/messages.pot +185 -129
  25. geovisio/translations/nl/LC_MESSAGES/messages.mo +0 -0
  26. geovisio/translations/nl/LC_MESSAGES/messages.po +292 -63
  27. geovisio/translations/oc/LC_MESSAGES/messages.mo +0 -0
  28. geovisio/translations/oc/LC_MESSAGES/messages.po +818 -0
  29. geovisio/translations/pl/LC_MESSAGES/messages.po +1 -1
  30. geovisio/translations/sv/LC_MESSAGES/messages.mo +0 -0
  31. geovisio/translations/sv/LC_MESSAGES/messages.po +4 -3
  32. geovisio/translations/ti/LC_MESSAGES/messages.mo +0 -0
  33. geovisio/translations/ti/LC_MESSAGES/messages.po +762 -0
  34. geovisio/translations/zh_Hant/LC_MESSAGES/messages.po +1 -1
  35. geovisio/utils/annotations.py +14 -17
  36. geovisio/utils/auth.py +14 -13
  37. geovisio/utils/cql2.py +2 -2
  38. geovisio/utils/fields.py +14 -2
  39. geovisio/utils/items.py +44 -0
  40. geovisio/utils/model_query.py +2 -2
  41. geovisio/utils/pic_shape.py +1 -1
  42. geovisio/utils/pictures.py +111 -18
  43. geovisio/utils/semantics.py +32 -3
  44. geovisio/utils/sentry.py +1 -1
  45. geovisio/utils/sequences.py +51 -34
  46. geovisio/utils/upload_set.py +285 -198
  47. geovisio/utils/website.py +1 -1
  48. geovisio/web/annotations.py +209 -68
  49. geovisio/web/auth.py +1 -1
  50. geovisio/web/collections.py +26 -22
  51. geovisio/web/configuration.py +24 -4
  52. geovisio/web/docs.py +93 -11
  53. geovisio/web/items.py +197 -121
  54. geovisio/web/params.py +44 -31
  55. geovisio/web/pictures.py +34 -0
  56. geovisio/web/tokens.py +49 -1
  57. geovisio/web/upload_set.py +150 -32
  58. geovisio/web/users.py +4 -4
  59. geovisio/web/utils.py +2 -2
  60. geovisio/workers/runner_pictures.py +128 -23
  61. {geovisio-2.9.0.dist-info → geovisio-2.10.0.dist-info}/METADATA +13 -13
  62. geovisio-2.10.0.dist-info/RECORD +105 -0
  63. geovisio-2.9.0.dist-info/RECORD +0 -98
  64. {geovisio-2.9.0.dist-info → geovisio-2.10.0.dist-info}/WHEEL +0 -0
  65. {geovisio-2.9.0.dist-info → geovisio-2.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -55,7 +55,7 @@ class Collections:
55
55
  """
56
56
 
57
57
  collections: List[Dict[Any, Any]] = field(default_factory=lambda: [])
58
- # Bounds of the field used by the first field of the `ORDER BY` (usefull especially for pagination)
58
+ # Bounds of the field used by the first field of the `ORDER BY` (useful especially for pagination)
59
59
  query_bounds: Optional[Bounds] = None
60
60
 
61
61
 
@@ -157,23 +157,24 @@ def get_collections(request: CollectionsRequest) -> Collections:
157
157
  s.min_picture_ts AS mints,
158
158
  s.max_picture_ts AS maxts,
159
159
  s.nb_pictures AS nbpic,
160
+ s.upload_set_id,
160
161
  {status},
161
162
  s.computed_capture_date AS datetime,
162
163
  s.user_agent,
163
164
  ROUND(ST_Length(s.geom::geography)) / 1000 AS length_km,
164
165
  s.computed_h_pixel_density,
165
166
  s.computed_gps_accuracy,
166
- t.semantics
167
+ COALESCE(seq_sem.semantics, '[]'::json) AS semantics
167
168
  FROM sequences s
168
169
  LEFT JOIN accounts on s.account_id = accounts.id
169
170
  LEFT JOIN (
170
- SELECT sequence_id, json_agg(json_strip_nulls(json_build_object(
171
- 'key', key,
172
- 'value', value
173
- )) ORDER BY key, value) AS semantics
174
- FROM sequences_semantics
175
- GROUP BY sequence_id
176
- ) t ON t.sequence_id = s.id
171
+ SELECT sequence_id, json_agg(json_strip_nulls(json_build_object(
172
+ 'key', key,
173
+ 'value', value
174
+ )) ORDER BY key, value) AS semantics
175
+ FROM sequences_semantics
176
+ GROUP BY sequence_id
177
+ ) seq_sem ON seq_sem.sequence_id = s.id
177
178
  WHERE {filter}
178
179
  ORDER BY {order1}
179
180
  LIMIT {limit}
@@ -427,7 +428,7 @@ def sort_collection(db, collectionId: UUID, sortby: CollectionSort):
427
428
  """
428
429
  Sort a collection by a given parameter
429
430
 
430
- Note: the transaction is not commited at the end, you need to commit it or use an autocommit connection
431
+ Note: the transaction is not committed at the end, you need to commit it or use an autocommit connection
431
432
  """
432
433
 
433
434
  # Remove existing order, and keep list of pictures IDs
@@ -519,8 +520,8 @@ def update_headings(
519
520
  db,
520
521
  sequenceId: UUID,
521
522
  editingAccount: Optional[UUID] = None,
522
- relativeHeading: int = 0,
523
- updateOnlyMissing: bool = True,
523
+ relativeHeading: Optional[int] = None,
524
+ updateOnlyMissing: Optional[bool] = None,
524
525
  ):
525
526
  """Defines pictures heading according to sequence path.
526
527
  Database is not committed in this function, to make entry definitively stored
@@ -532,27 +533,42 @@ def update_headings(
532
533
  Database connection
533
534
  sequenceId : uuid
534
535
  The sequence's uuid, as stored in the database
535
- relativeHeading : int
536
+ relativeHeading : Optional[int]
536
537
  Camera relative orientation compared to path, in degrees clockwise.
537
538
  Example: 0° = looking forward, 90° = looking to right, 180° = looking backward, -90° = looking left.
538
- updateOnlyMissing : bool
539
+ If not provided, will first use the relative_heading stored in the sequence's metadata, then the relative_heading of its upload_set (if if none is set, default to 0).
540
+ updateOnlyMissing : Optional[bool]
539
541
  If true, doesn't change existing heading values in database
542
+ if not provided, we check if some relative heading has been set (either in the sequence or in its upload_set), and if so, we recompute all
540
543
  """
541
-
542
544
  db.execute(
543
545
  SQL(
544
- """
545
- WITH h AS (
546
+ """WITH
547
+ relative_heading AS (
548
+ SELECT COALESCE(
549
+ %(relativeHeading)s,
550
+ (SELECT (metadata->>'relative_heading')::int FROM sequences WHERE id = %(seq)s),
551
+ (SELECT upload_sets.relative_heading FROM sequences JOIN upload_sets ON sequences.upload_set_id = upload_sets.id WHERE sequences.id = %(seq)s),
552
+ 0
553
+ ) AS heading,
554
+ COALESCE(
555
+ %(update_only_missing)s,
556
+ (SELECT metadata->'relative_heading' IS NULL FROM sequences WHERE id = %(seq)s and metadata ? 'relative_heading'),
557
+ (SELECT upload_sets.relative_heading IS NULL FROM sequences JOIN upload_sets ON sequences.upload_set_id = upload_sets.id WHERE sequences.id = %(seq)s)
558
+ ) AS update_only_missing
559
+ )
560
+ , h AS (
546
561
  SELECT
547
562
  p.id,
548
563
  p.heading AS old_heading,
549
564
  CASE
550
565
  WHEN LEAD(sp.rank) OVER othpics IS NULL AND LAG(sp.rank) OVER othpics IS NULL
551
- THEN NULL
566
+ -- if there is a single picture, we take the relative heading directly
567
+ THEN (SELECT heading FROM relative_heading)
552
568
  WHEN LEAD(sp.rank) OVER othpics IS NULL
553
- THEN (360 + FLOOR(DEGREES(ST_Azimuth(LAG(p.geom) OVER othpics, p.geom)))::int + (%(diff)s %% 360)) %% 360
569
+ THEN (360 + FLOOR(DEGREES(ST_Azimuth(LAG(p.geom) OVER othpics, p.geom)))::int + ((SELECT heading FROM relative_heading) %% 360)) %% 360
554
570
  ELSE
555
- (360 + FLOOR(DEGREES(ST_Azimuth(p.geom, LEAD(p.geom) OVER othpics)))::int + (%(diff)s %% 360)) %% 360
571
+ (360 + FLOOR(DEGREES(ST_Azimuth(p.geom, LEAD(p.geom) OVER othpics)))::int + ((SELECT heading FROM relative_heading) %% 360)) %% 360
556
572
  END AS heading
557
573
  FROM pictures p
558
574
  JOIN sequences_pictures sp ON sp.pic_id = p.id AND sp.seq_id = %(seq)s
@@ -561,13 +577,15 @@ def update_headings(
561
577
  UPDATE pictures p
562
578
  SET heading = h.heading, heading_computed = true {editing_account}
563
579
  FROM h
564
- WHERE h.id = p.id {update_missing}
580
+ WHERE h.id = p.id AND (
581
+ (SELECT NOT update_only_missing FROM relative_heading)
582
+ OR (p.heading IS NULL OR p.heading = 0 OR p.heading_computed) -- # lots of camera have heading set to 0 for unset heading, so we recompute the heading when it's 0 too, even if this could be a valid value
583
+ )
565
584
  """
566
585
  ).format(
567
- update_missing=SQL(" AND (p.heading IS NULL OR p.heading = 0 OR p.heading_computed)") if updateOnlyMissing else SQL(""),
568
586
  editing_account=SQL(", last_account_to_edit = %(account)s") if editingAccount is not None else SQL(""),
569
- ), # lots of camera have heading set to 0 for unset heading, so we recompute the heading when it's 0 too, even if this could be a valid value
570
- {"seq": sequenceId, "diff": relativeHeading, "account": editingAccount},
587
+ ),
588
+ {"seq": sequenceId, "relativeHeading": relativeHeading, "account": editingAccount, "update_only_missing": updateOnlyMissing},
571
589
  )
572
590
 
573
591
 
@@ -593,14 +611,13 @@ def finalize(cursor, seqId: UUID, logger: logging.Logger = logging.getLogger()):
593
611
  span.set_data("sequence_id", seqId)
594
612
  logger.debug(f"Finalizing sequence {seqId}")
595
613
 
596
- with utils.time.log_elapsed(f"Finalizing sequence {seqId}"):
597
- # Complete missing headings in pictures
598
- update_headings(cursor, seqId)
614
+ # Complete missing headings in pictures
615
+ update_headings(cursor, seqId)
599
616
 
600
- # Change sequence database status in DB
601
- # Also generates data in computed columns
602
- cursor.execute(
603
- """WITH
617
+ # Change sequence database status in DB
618
+ # Also generates data in computed columns
619
+ cursor.execute(
620
+ """WITH
604
621
  aggregated_pictures AS (
605
622
  SELECT
606
623
  sp.seq_id,
@@ -629,10 +646,10 @@ computed_gps_accuracy = gpsacc
629
646
  FROM aggregated_pictures
630
647
  WHERE id = %(seq)s
631
648
  """,
632
- {"seq": seqId},
633
- )
649
+ {"seq": seqId},
650
+ )
634
651
 
635
- logger.info(f"Sequence {seqId} is ready")
652
+ logger.info(f"Sequence {seqId} is ready")
636
653
 
637
654
 
638
655
  def update_pictures_grid() -> Optional[datetime.datetime]: