pikobs 3.0.415__tar.gz → 3.0.416__tar.gz

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 (171) hide show
  1. {pikobs-3.0.415 → pikobs-3.0.416}/CHANGELOG.md +4 -0
  2. {pikobs-3.0.415/pikobs.egg-info → pikobs-3.0.416}/PKG-INFO +1 -1
  3. pikobs-3.0.416/VERSION +1 -0
  4. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/scatter/scatter.py +157 -24
  5. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_scatter.sh +1 -1
  6. {pikobs-3.0.415 → pikobs-3.0.416/pikobs.egg-info}/PKG-INFO +1 -1
  7. pikobs-3.0.415/VERSION +0 -1
  8. {pikobs-3.0.415 → pikobs-3.0.416}/.gitignore +0 -0
  9. {pikobs-3.0.415 → pikobs-3.0.416}/MANIFEST.in +0 -0
  10. {pikobs-3.0.415 → pikobs-3.0.416}/README.md +0 -0
  11. {pikobs-3.0.415 → pikobs-3.0.416}/clear.sh +0 -0
  12. {pikobs-3.0.415 → pikobs-3.0.416}/conda_build/pikobs/activate.sh +0 -0
  13. {pikobs-3.0.415 → pikobs-3.0.416}/conda_build/pikobs/build.sh +0 -0
  14. {pikobs-3.0.415 → pikobs-3.0.416}/conda_build/pikobs/meta.yaml +0 -0
  15. {pikobs-3.0.415 → pikobs-3.0.416}/conda_build/pikobs/pikobs.yml +0 -0
  16. {pikobs-3.0.415 → pikobs-3.0.416}/docs/Makefile +0 -0
  17. {pikobs-3.0.415 → pikobs-3.0.416}/docs/make.bat +0 -0
  18. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/cardio.rst +0 -0
  19. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/conf.py +0 -0
  20. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/families.rst +0 -0
  21. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/flag.rst +0 -0
  22. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/flags_criteria.rst +0 -0
  23. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/histogram.rst +0 -0
  24. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/index.rst +0 -0
  25. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/mapobs.rst +0 -0
  26. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/obscountdb.rst +0 -0
  27. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/obstimedb.rst +0 -0
  28. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/pikobsburp2rdb.rst +0 -0
  29. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/profile.rst +0 -0
  30. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/profile_ft.rst +0 -0
  31. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/profile_ft2.rst +0 -0
  32. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/projection.rst +0 -0
  33. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/region.rst +0 -0
  34. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/scatter.rst +0 -0
  35. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/spatial.rst +0 -0
  36. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/timeserie.rst +0 -0
  37. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/unittest.rst +0 -0
  38. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/varno.rst +0 -0
  39. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/vdedr.rst +0 -0
  40. {pikobs-3.0.415 → pikobs-3.0.416}/docs/source/zone.rst +0 -0
  41. {pikobs-3.0.415 → pikobs-3.0.416}/env/.mambarc +0 -0
  42. {pikobs-3.0.415 → pikobs-3.0.416}/env/conda-meta/history +0 -0
  43. {pikobs-3.0.415 → pikobs-3.0.416}/env/etc/aau_token +0 -0
  44. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/__init__.py +0 -0
  45. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/__not_used/plot_proj.py +0 -0
  46. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/__not_used/vdedr2.py +0 -0
  47. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/__not_used/vdedr3.py +0 -0
  48. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/cardio/__init__.py +0 -0
  49. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/cardio/cardio.py +0 -0
  50. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/cardio/cardio_plot.py +0 -0
  51. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/cardio/cardio_plot_old.py +0 -0
  52. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/__init__.py +0 -0
  53. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/delete_folder.py +0 -0
  54. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/families.py +0 -0
  55. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/familyobs.py +0 -0
  56. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/flags_criteria.py +0 -0
  57. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/regionsobs.py +0 -0
  58. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/special_family.py +0 -0
  59. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/type_boxes.py +0 -0
  60. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/type_projection.py +0 -0
  61. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/configobs/type_varno.py +0 -0
  62. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/extension/color_mapping.json +0 -0
  63. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/extension/libudfsqlite-shared.so +0 -0
  64. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/__init__.py +0 -0
  65. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/flags.py +0 -0
  66. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/flags_count.py +0 -0
  67. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/flags_plot.py +0 -0
  68. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/flags_plot0.py +0 -0
  69. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/flags_plot3.py +0 -0
  70. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/flags_plotv2.py +0 -0
  71. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo.py +0 -0
  72. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo2.py +0 -0
  73. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo3.py +0 -0
  74. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo4.py +0 -0
  75. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo5.py +0 -0
  76. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo7.py +0 -0
  77. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo8.py +0 -0
  78. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/flags/plotpo9.py +0 -0
  79. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/histogram/__init__.py +0 -0
  80. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/histogram/histogram.py +0 -0
  81. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/histogram/histogram_plot.py +0 -0
  82. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/mapobs/__init__.py +0 -0
  83. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/mapobs/color.j +0 -0
  84. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/mapobs/mapobs.py +0 -0
  85. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscountdb/__init__.py +0 -0
  86. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscountdb/obscountdb.py +0 -0
  87. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscountdb/obscountdb_old.py +0 -0
  88. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscountdb/obscountdb_plot.py +0 -0
  89. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscutoff/__init__.py +0 -0
  90. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscutoff/obscutoff.py +0 -0
  91. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obscutoff/obscutoff_plot.py +0 -0
  92. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obstimedb/__init__.py +0 -0
  93. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obstimedb/obstimedb.py +0 -0
  94. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/obstimedb/obstimedb_plot.py +0 -0
  95. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/pbs_submit/__init__.py +0 -0
  96. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/pbs_submit/pbs_submit.py +0 -0
  97. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/pikobsburp2rdb/__init__.py +0 -0
  98. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/pikobsburp2rdb/pikobsburp2rdb.py +0 -0
  99. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/profile/__init__.py +0 -0
  100. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/profile/profile.py +0 -0
  101. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/profile/profile_plot.py +0 -0
  102. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/progps/__init__.py +0 -0
  103. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/progps/progps.py +0 -0
  104. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/progps/progps_old.py +0 -0
  105. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/progps2/__init__.py +0 -0
  106. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/progps2/progps2.py +0 -0
  107. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/scatter/__init__.py +0 -0
  108. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/remove.sh +0 -0
  109. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/remove2.py +0 -0
  110. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_2exp.sh +0 -0
  111. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_cardio.sh +0 -0
  112. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_cardio_lco.sh +0 -0
  113. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_cardio_sky.sh +0 -0
  114. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_flag.sh +0 -0
  115. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_histogra.sh +0 -0
  116. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_mapobs.sh +0 -0
  117. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_obscountdb.sh +0 -0
  118. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_obscountdb_1.sh +0 -0
  119. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_obstimedb.sh +0 -0
  120. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_pikobsburp2rdb.sh +0 -0
  121. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_profile.sh +0 -0
  122. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_profile_1.sh +0 -0
  123. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_profile_ra.sh +0 -0
  124. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_profile_radar.sh +0 -0
  125. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_profile_s.sh +0 -0
  126. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_progps.sh +0 -0
  127. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_progps2.sh +0 -0
  128. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_scatter_diff.sh +0 -0
  129. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_scatter_one.sh +0 -0
  130. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_scatter_two_sw.sh +0 -0
  131. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_spatial.sh +0 -0
  132. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_timeserie.sh +0 -0
  133. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_timeserie_radar.sh +0 -0
  134. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_vdedr.sh +0 -0
  135. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/run_zone2.sh +0 -0
  136. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/setup_pikobs.sh +0 -0
  137. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/script/setup_pikobs.sh.1 +0 -0
  138. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/spatial/__init__.py +0 -0
  139. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/spatial/spatial.py +0 -0
  140. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/spatial/spatial_core.py +0 -0
  141. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/timeserie/__init__.py +0 -0
  142. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/timeserie/timeserie.py +0 -0
  143. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/timeserie/timeserie_plot.py +0 -0
  144. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/unittestpikobs/__init__.py +0 -0
  145. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/unittestpikobs/test_pikobs.py +0 -0
  146. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/unittestpikobs/unittest_timeserie.py +0 -0
  147. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/vdedr/__init__.py +0 -0
  148. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/vdedr/vdedr.py +0 -0
  149. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/vdedr/vdedr_plot.py +0 -0
  150. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/web/__init__.py +0 -0
  151. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/web/viewer.py +0 -0
  152. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/zone/__init__.py +0 -0
  153. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/zone/zone.py +0 -0
  154. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs/zone/zone_plot.py +0 -0
  155. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs.egg-info/SOURCES.txt +0 -0
  156. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs.egg-info/dependency_links.txt +0 -0
  157. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs.egg-info/requires.txt +0 -0
  158. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs.egg-info/top_level.txt +0 -0
  159. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs_env.yml +0 -0
  160. {pikobs-3.0.415 → pikobs-3.0.416}/pikobs_env2.yml +0 -0
  161. {pikobs-3.0.415 → pikobs-3.0.416}/publique.sh +0 -0
  162. {pikobs-3.0.415 → pikobs-3.0.416}/publique.txt +0 -0
  163. {pikobs-3.0.415 → pikobs-3.0.416}/readme/flag_criteria.md +0 -0
  164. {pikobs-3.0.415 → pikobs-3.0.416}/readme/geographic.md +0 -0
  165. {pikobs-3.0.415 → pikobs-3.0.416}/readme/read_projection.md +0 -0
  166. {pikobs-3.0.415 → pikobs-3.0.416}/readme/readme_cardiograme.md +0 -0
  167. {pikobs-3.0.415 → pikobs-3.0.416}/readme/readme_scatter.md +0 -0
  168. {pikobs-3.0.415 → pikobs-3.0.416}/setup.cfg +0 -0
  169. {pikobs-3.0.415 → pikobs-3.0.416}/setup.py +0 -0
  170. {pikobs-3.0.415 → pikobs-3.0.416}/setup_pikobs.sh +0 -0
  171. {pikobs-3.0.415 → pikobs-3.0.416}/setup_pikobs.sh.1 +0 -0
@@ -1487,3 +1487,7 @@ Please use the following tags when editing this file:
1487
1487
  ## [3.0.415] 2026-09-17
1488
1488
  ### Added
1489
1489
  - bugs
1490
+
1491
+ ## [3.0.416] 2026-09-17
1492
+ ### Added
1493
+ - bugs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pikobs
3
- Version: 3.0.415
3
+ Version: 3.0.416
4
4
  Summary: pikobs
5
5
  Home-page: https://gitlab.science.gc.ca/dlo001/pikobs
6
6
  Author: David Lobon
pikobs-3.0.416/VERSION ADDED
@@ -0,0 +1 @@
1
+ 3.0.416
@@ -652,7 +652,10 @@ selector of the viewer:
652
652
 
653
653
  **significance** shows how sure the test is, from 0 to 100 %. Grey boxes
654
654
  stay at or below 95 % (darker when closer), orange ones are above 95 % and
655
- red ones above 99 %; the thick line on the colour bar marks 95 %. The box at
655
+ red ones above 99 %; the thick line on the colour bar marks 95 %. For
656
+ ``omp`` and ``oma``, a crossed box (``xxx``) passed both tests but its bias
657
+ and spread moved in opposite directions, so it is not counted (see *Why omp
658
+ and oma need both tests*). The box at
656
659
  the top right recalls which test was run and counts the significant boxes:
657
660
 
658
661
  .. image:: _static/scatter_cmp_omp_significance.png
@@ -661,7 +664,8 @@ the top right recalls which test was run and counts the significant boxes:
661
664
  :width: 100%
662
665
 
663
666
  **significant only** is the difference map with the same colours and the
664
- same scale, where only the boxes above 95 % are drawn. It is usually the
667
+ same scale, where only the boxes that pass are drawn (for ``omp`` / ``oma``:
668
+ both tests, same direction). It is usually the
665
669
  one to show in a meeting:
666
670
 
667
671
  .. image:: _static/scatter_cmp_omp_sigonly.png
@@ -777,16 +781,108 @@ the difference only carries the change of the background; that is why the
777
781
  paired test sees small bias changes that an independent test would miss.
778
782
  ``bcorr`` uses the same test on the bias correction.
779
783
 
780
- An ``omp`` or ``oma`` box is significant only when **both** tests are
781
- above 95 %, and the significance map shows the lower of the two. On boxes of
782
- 10° or more the confidences are written in the box, e.g. ``t99 F97``. An
783
- experience that moves the bias without touching the spread therefore stays
784
- mostly non-significant on the ``omp`` map; its ``t`` value in the box shows
785
- it.
784
+ An ``omp`` or ``oma`` box counts only when **both** tests are above 95 %
785
+ **and** the bias and the spread moved in the same direction. The
786
+ significance map shows the lower of the two confidences, and on boxes of
787
+ 10° or more both are written in the box, e.g. ``t99 F97``. The next section
788
+ explains why both are needed.
789
+
790
+ Why omp and oma need both tests
791
+ -------------------------------
792
+
793
+ Think of the observation as the centre of a target, ``[O]``, and of each
794
+ O-B as a shot. The **t-test** looks at the aim: did the average shot move
795
+ closer to the centre, or further? The **F-test** looks at the hand: are the
796
+ shots more grouped, or more scattered?
797
+
798
+ Both tests are two-sided. Passing one means *this changed more than chance
799
+ allows*, in either direction; the sign of the change says which way. So a
800
+ box needs both tests above 95 %, and both changes pointing the same way.
801
+
802
+ **Case 1: better aim, shakier hand.** The experience brings the average
803
+ onto the centre, but its shots are all over the place.
804
+
805
+ .. code-block:: text
806
+
807
+ CONTROL EXPERIENCE
808
+ off-centre, grouped centred, scattered
809
+
810
+ E
811
+ CCC E
812
+ [O] CCC [O]
813
+ CCC E E
814
+ E
815
+
816
+ t-test: passes, the bias is smaller (better)
817
+ F-test: passes, the spread is larger (worse)
818
+
819
+ The average looks perfect, but the model lost its consistency. The two
820
+ changes disagree, so the box is **not drawn** on the significant-only map
821
+ and is crossed (``xxx``) on the significance map.
822
+
823
+ **Case 2: steady hand, wrong aim.** The experience groups its shots
824
+ beautifully, but the whole group has drifted away from the centre.
825
+
826
+ .. code-block:: text
827
+
828
+ CONTROL EXPERIENCE
829
+ centred, scattered grouped, off-centre
830
+
831
+ C
832
+ C C EEE
833
+ [O] [O] EEE
834
+ C C EEE
835
+ C
836
+
837
+ t-test: passes, the bias is larger (worse)
838
+ F-test: passes, the spread is smaller (better)
839
+
840
+ The spread went down, but a systematic error came in. Again the changes
841
+ disagree: **not drawn**, crossed on the significance map.
842
+
843
+ **Case 3: better on both.** The experience corrects the bias and tightens
844
+ the spread. This is the result you are looking for.
845
+
846
+ .. code-block:: text
847
+
848
+ CONTROL EXPERIENCE
849
+ off-centre and scattered centred and grouped
850
+
851
+ C
852
+ EEE
853
+ [O] E[O]E
854
+ C EEE
855
+ C
856
+
857
+ t-test: passes, the bias is smaller (better)
858
+ F-test: passes, the spread is smaller (better)
859
+
860
+ The box is drawn in **red** on the significant-only map and counted as
861
+ *better*.
862
+
863
+ **Case 4: worse on both.** The mirror image of case 3: the experience moves
864
+ away from the centre and scatters more. The box is drawn in **blue** and
865
+ counted as *worse*, which is just as useful to know.
866
+
867
+ A last case is the quiet one: the bias improves but the spread does not
868
+ change at all. The t-test passes, the F-test does not, and the box stays
869
+ out of the significant-only map. Its ``t`` value, written in the box on the
870
+ significance map, still shows that something moved.
871
+
872
+ In one line, for ``omp`` and ``oma``:
873
+
874
+ .. code-block:: text
875
+
876
+ drawn in red = bias better AND spread better, both above 95 %
877
+ drawn in blue = bias worse AND spread worse, both above 95 %
878
+ not drawn = anything else (crossed when both pass in opposite directions)
786
879
 
787
880
  Reading the tests
788
881
  -----------------
789
882
 
883
+ * ``stdomp`` and ``stdoma`` only look at the spread, so the F-test alone
884
+ decides there, and ``bcorr`` only looks at the mean. Only ``omp`` and
885
+ ``oma`` combine both.
790
886
  * The F-test treats the two runs as independent samples. With common
791
887
  observations they are strongly correlated, which makes the F-test
792
888
  cautious: a real change of the spread needs more observations to pass.
@@ -2636,6 +2732,21 @@ def _paired_t_confidence(mx, my, vx, vy, cxy, N) -> np.ndarray:
2636
2732
  return conf
2637
2733
 
2638
2734
 
2735
+ def _both_tests(d_bias, d_spread, t_conf, f_conf):
2736
+ """omp / oma: a box counts only when the bias and the spread both changed
2737
+ significantly AND in the same direction (both better or both worse).
2738
+
2739
+ Returns (values, significant, confidences, kind); confidences also
2740
+ carries 'mixed', the boxes where both tests pass but the bias and the
2741
+ spread moved in opposite directions.
2742
+ """
2743
+ both = _is_significant(t_conf) & _is_significant(f_conf)
2744
+ same = np.sign(d_bias) == np.sign(d_spread)
2745
+ mixed = both & ~same
2746
+ return (d_bias, both & same,
2747
+ {'t': t_conf, 'F': f_conf, 'mixed': mixed}, 'improve')
2748
+
2749
+
2639
2750
  def _paired_metric(fonction: str, N, SX, SY, SXX, SYY, SXY
2640
2751
  ) -> Tuple[np.ndarray, np.ndarray,
2641
2752
  Dict[str, np.ndarray], str]:
@@ -2664,8 +2775,7 @@ def _paired_metric(fonction: str, N, SX, SY, SXX, SYY, SXY
2664
2775
 
2665
2776
  t_conf = _paired_t_confidence(mx, my, vx, vy, cxy, N)
2666
2777
  values = np.abs(my) - np.abs(mx)
2667
- return (values, _is_significant(t_conf) & _is_significant(f_conf),
2668
- {'t': t_conf, 'F': f_conf}, 'improve')
2778
+ return _both_tests(values, s_exp - s_ref, t_conf, f_conf)
2669
2779
 
2670
2780
 
2671
2781
  def _diff_metric(fonction: str, avg1, avg2, std1, std2, bc1, bc2, n1, n2,
@@ -2703,8 +2813,7 @@ def _diff_metric(fonction: str, avg1, avg2, std1, std2, bc1, bc2, n1, n2,
2703
2813
 
2704
2814
  t_conf = _ttest_confidence(avg1, std1, n1, avg2, std2, n2)
2705
2815
  values = np.abs(avg2) - np.abs(avg1)
2706
- return (values, _is_significant(t_conf) & _is_significant(f_conf),
2707
- {'t': t_conf, 'F': f_conf}, 'improve')
2816
+ return _both_tests(values, s_exp - s_ref, t_conf, f_conf)
2708
2817
 
2709
2818
 
2710
2819
  _CBAR_DIFF: Dict[str, str] = {
@@ -2732,8 +2841,8 @@ _CBAR_SINGLE: Dict[str, str] = {
2732
2841
 
2733
2842
 
2734
2843
  _TEST_TEXT = {
2735
- 'omp': "t-test (bias O-B) + F-test (σ O-B)\nshown: the lower confidence",
2736
- 'oma': "t-test (bias O-A) + F-test (σ O-A)\nshown: the lower confidence",
2844
+ 'omp': "t-test (bias O-B) + F-test (σ O-B)\nboth > 95 %, same direction",
2845
+ 'oma': "t-test (bias O-A) + F-test (σ O-A)\nboth > 95 %, same direction",
2737
2846
  'stdomp': "F-test on σ(O-B), F = σ²big / σ²small",
2738
2847
  'stdoma': "F-test on σ(O-A), F = σ²big / σ²small",
2739
2848
  'bcorr': "Welch t-test on the mean bias corr.",
@@ -2741,10 +2850,10 @@ _TEST_TEXT = {
2741
2850
 
2742
2851
 
2743
2852
  _TEST_TEXT_PAIRED = {
2744
- 'omp': "paired t-test (bias) + F-test (σ), O-B\n"
2745
- "of common obs, lower confidence shown",
2746
- 'oma': "paired t-test (bias) + F-test (σ), O-A\n"
2747
- "of common obs, lower confidence shown",
2853
+ 'omp': "paired t-test (bias) + F-test (σ)\n"
2854
+ "on O-B of common obs, both > 95 %, same direction",
2855
+ 'oma': "paired t-test (bias) + F-test (σ)\n"
2856
+ "on O-A of common obs, both > 95 %, same direction",
2748
2857
  'stdomp': "F-test on σ(O-B) of common obs,\nF = σ²big / σ²small",
2749
2858
  'stdoma': "F-test on σ(O-A) of common obs,\nF = σ²big / σ²small",
2750
2859
  'bcorr': "paired t-test on the bias corr., common obs",
@@ -2753,7 +2862,8 @@ _TEST_TEXT_PAIRED = {
2753
2862
 
2754
2863
  def _info_text(panel, fonction, is_diff, kind, confs, values, diff_values,
2755
2864
  signif, in_axes, boundaries, on_map_obs, on_map_ref, n_days,
2756
- avg=None, std=None, n_black=0, n_pairs=None) -> str:
2865
+ avg=None, std=None, n_black=0, n_pairs=None,
2866
+ n_mixed=0) -> str:
2757
2867
  """Text of the box at the top right of a map."""
2758
2868
  if not is_diff:
2759
2869
  if fonction in ('dens', 'nobs'):
@@ -2786,6 +2896,9 @@ def _info_text(panel, fonction, is_diff, kind, confs, values, diff_values,
2786
2896
  n_wor = int((box & signif & (diff_values > 0)).sum())
2787
2897
  counts += f'\n{n_bet} better (red), {n_wor} worse (blue)'
2788
2898
 
2899
+ mixed_line = (f'\nmixed: {n_mixed} boxes, bias and σ changed\n'
2900
+ f'in opposite directions (not counted)'
2901
+ if n_mixed else '')
2789
2902
  black_line = (f'\nblack: {n_black} boxes not compared, no\n'
2790
2903
  + ('common observation in control and experience'
2791
2904
  if n_pairs is not None else
@@ -2795,17 +2908,19 @@ def _info_text(panel, fonction, is_diff, kind, confs, values, diff_values,
2795
2908
  if panel == PANEL_SIGONLY:
2796
2909
  return (f'Only boxes with confidence > {_MIN_CONFIDENCE:.0f} %\n'
2797
2910
  f'({tests.get(fonction, "").splitlines()[0]})\n'
2798
- f'{counts}\n{nobs_line}{black_line}')
2911
+ f'{counts}\n{nobs_line}{mixed_line}{black_line}')
2799
2912
 
2800
2913
  if panel == PANEL_CONF:
2801
2914
  return (f'{tests.get(fonction, "")}\n'
2802
2915
  f'(1 - p) x 100, > {_MIN_CONFIDENCE:.0f} % = significant\n'
2803
- f'{counts}\n{nobs_line}{black_line}')
2916
+ f'{counts}\n{nobs_line}'
2917
+ + (mixed_line.replace('boxes,', 'boxes (xxx),')
2918
+ if n_mixed else '') + black_line)
2804
2919
 
2805
2920
  text = nobs_line
2806
2921
  if confs:
2807
2922
  text += f'\n{counts.replace("boxes", f"boxes at {_MIN_CONFIDENCE:.0f} %")}'
2808
- return text + black_line
2923
+ return text + mixed_line + black_line
2809
2924
 
2810
2925
 
2811
2926
  def _render_tile_map(task: Dict[str, Any],
@@ -2957,6 +3072,10 @@ def _render_tile_map_impl(task: Dict[str, Any],
2957
3072
  if signif is None:
2958
3073
  signif = np.ones(len(values), dtype=bool)
2959
3074
 
3075
+ mixed = confs.pop('mixed', None) if confs else None
3076
+ if mixed is None:
3077
+ mixed = np.zeros(len(values), dtype=bool)
3078
+
2960
3079
  # combined confidence: the weakest test decides (omp/oma need both)
2961
3080
  conf = None
2962
3081
  if confs:
@@ -3038,6 +3157,7 @@ def _render_tile_map_impl(task: Dict[str, Any],
3038
3157
  on_map_ref = float(n1[in_axes].sum()) if is_diff else 0.0
3039
3158
 
3040
3159
  patches, patch_colors = [], []
3160
+ patches_mixed = []
3041
3161
  for i in np.flatnonzero(in_axes):
3042
3162
  if panel == PANEL_SIGONLY and not signif[i]:
3043
3163
  continue
@@ -3058,12 +3178,21 @@ def _render_tile_map_impl(task: Dict[str, Any],
3058
3178
  patches.append(plt.Polygon(
3059
3179
  _project_polygon(proj_obj, lat[i], lon[i], deltax, deltay, pc)))
3060
3180
  patch_colors.append(facecolors[i])
3181
+ if panel == PANEL_CONF and mixed[i]:
3182
+ patches_mixed.append(plt.Polygon(
3183
+ _project_polygon(proj_obj, lat[i], lon[i], deltax, deltay, pc)))
3061
3184
 
3062
3185
  if patches:
3063
3186
  ax.add_collection(PatchCollection(
3064
3187
  patches, facecolors=patch_colors,
3065
3188
  edgecolors='black', linewidths=0.2, alpha=ALPHA_TILES, zorder=4))
3066
3189
 
3190
+ if patches_mixed:
3191
+ # both tests pass, but bias and spread moved in opposite directions
3192
+ ax.add_collection(PatchCollection(
3193
+ patches_mixed, facecolors='none', edgecolors='#3a3a3a',
3194
+ linewidths=0.3, hatch='xxx', zorder=5))
3195
+
3067
3196
  if exclusive:
3068
3197
  ax.add_collection(PatchCollection(
3069
3198
  [plt.Polygon(_project_polygon(proj_obj, lt, ln, deltax, deltay, pc))
@@ -3132,7 +3261,8 @@ def _render_tile_map_impl(task: Dict[str, Any],
3132
3261
  avg if not is_diff else None,
3133
3262
  std if not is_diff else None,
3134
3263
  n_black=len(exclusive),
3135
- n_pairs=n_pairs_on_map)
3264
+ n_pairs=n_pairs_on_map,
3265
+ n_mixed=int((mixed & in_axes).sum()))
3136
3266
  # top right, next to the title block
3137
3267
  info_txt = ax.text(1.0, 1.02, textstr, transform=ax.transAxes,
3138
3268
  fontsize=11, ha='right', va='bottom',
@@ -3265,7 +3395,10 @@ _INTRO_DIFF = [
3265
3395
  "<b>significant only</b> is the difference map where only the boxes "
3266
3396
  "above 95 % are drawn. The spread is tested with the F-test "
3267
3397
  "F = σ²larger / σ²smaller, two-sided; the bias and bcorr with a paired "
3268
- "t-test; omp and oma need both, and the map shows the lower confidence. "
3398
+ "t-test. omp and oma need both tests above 95 % and the bias and the "
3399
+ "spread moving the same way (both better: red, both worse: blue); when "
3400
+ "they move in opposite directions the box is crossed on the significance "
3401
+ "map and left out. The map shows the lower confidence. "
3269
3402
  "obs, nobs and dens have no test; bcorr exists for radiances only.",
3270
3403
 
3271
3404
  "The scale is symmetric and adapts to each map (steps like 0.1, 0.2, 0.3, "
@@ -46,7 +46,7 @@ CONTROL_NAME="Control"
46
46
  # Output directory. WARNING: wiped on each run to prevent ghost files.
47
47
  # Will contain one subdir per family with the .db files and .png maps,
48
48
  # plus an interactive HTML viewer at pikobs_scatter_viewer.html.
49
- PATHWORK="/home/dlo001/sites8/pikobs_scatter_exp"
49
+ PATHWORK="/home/dlo001/sites8/pikobs_scatter_exp2"
50
50
 
51
51
  # ---- Time window ---------------------------------------------------------
52
52
  # Processing window in YYYYMMDDHH format (UTC). Inclusive on both ends,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pikobs
3
- Version: 3.0.415
3
+ Version: 3.0.416
4
4
  Summary: pikobs
5
5
  Home-page: https://gitlab.science.gc.ca/dlo001/pikobs
6
6
  Author: David Lobon
pikobs-3.0.415/VERSION DELETED
@@ -1 +0,0 @@
1
- 3.0.415
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes