pysits 2.0.0.dev1__tar.gz → 2.0.0.dev3__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.
- pysits-2.0.0.dev3/.claude/settings.local.json +16 -0
- pysits-2.0.0.dev3/.github/workflows/tests.yaml +96 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/PKG-INFO +11 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pyproject.toml +10 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/__init__.py +33 -12
- pysits-2.0.0.dev3/pysits/backend/arrow.py +106 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/backend/pkgs.py +6 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/tibble.py +38 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/impute_linear.md +2 -1
- pysits-2.0.0.dev1/pysits/docs/content/impute_median.md → pysits-2.0.0.dev3/pysits/docs/content/impute_mean.md +2 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/impute_mean_window.md +3 -3
- pysits-2.0.0.dev3/pysits/docs/content/impute_median.md +9 -0
- pysits-2.0.0.dev3/pysits/docs/content/plot.md +117 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_accuracy.md +21 -20
- pysits-2.0.0.dev3/pysits/docs/content/sits_accuracy_summary.md +11 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_add_base_cube.md +1 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_apply.md +24 -26
- pysits-2.0.0.dev3/pysits/docs/content/sits_as_geopandas.md +28 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_barlow_twins.md +17 -19
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_bbox.md +6 -6
- pysits-2.0.0.dev3/pysits/docs/content/sits_classify.md +88 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_cluster_dendro.md +15 -14
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_cluster_frequency.md +1 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_colors_qgis.md +3 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_colors_show.md +2 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_combine_predictions.md +2 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_confidence_sampling.md +2 -1
- pysits-2.0.0.dev3/pysits/docs/content/sits_config.md +29 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_config_user_file.md +1 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_contrastive_learning.md +11 -11
- pysits-2.0.0.dev3/pysits/docs/content/sits_cube.md +80 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_cube_copy.md +17 -14
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_encode.md +21 -24
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_formula_logref.md +5 -5
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_geo_dist.md +3 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_get_class.md +4 -5
- pysits-2.0.0.dev3/pysits/docs/content/sits_get_data.md +57 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_get_probs.md +5 -7
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_kfold_validate.md +7 -6
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_label_classification.md +13 -14
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_labels.md +4 -4
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_labels_summary.md +2 -2
- pysits-2.0.0.dev3/pysits/docs/content/sits_lightgbm.md +48 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_lighttae.md +13 -12
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_list_collections.md +1 -1
- pysits-2.0.0.dev3/pysits/docs/content/sits_lstm_fcn.md +76 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_merge.md +7 -7
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_mixture_model.md +8 -8
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_mlp.md +20 -20
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_model_export.md +3 -3
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_mosaic.md +29 -25
- pysits-2.0.0.dev3/pysits/docs/content/sits_parallel.md +52 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_patterns.md +1 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_pre_train.md +5 -5
- pysits-2.0.0.dev3/pysits/docs/content/sits_pred_features.md +21 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_pred_normalize.md +3 -3
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_pred_sample.md +1 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_predictors.md +1 -1
- pysits-2.0.0.dev3/pysits/docs/content/sits_random_sampling.md +30 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_reclassify.md +35 -41
- pysits-2.0.0.dev3/pysits/docs/content/sits_reduce.md +62 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_reduce_imbalance.md +2 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_regularize.md +11 -11
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_resnet.md +4 -4
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_roi_to_tiles.md +5 -5
- pysits-2.0.0.dev3/pysits/docs/content/sits_sample.md +27 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_sampling_design.md +3 -5
- pysits-2.0.0.dev3/pysits/docs/content/sits_sankey.md +60 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_segment.md +4 -5
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_select.md +7 -10
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_show_prediction.md +1 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_slic.md +13 -13
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_smooth.md +3 -3
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_snic.md +9 -9
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_som_evaluate_cluster.md +1 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_som_map.md +20 -21
- pysits-2.0.0.dev3/pysits/docs/content/sits_som_remove_samples.md +28 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_ssl_lejepa.md +6 -6
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_ssl_mae.md +20 -17
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_ssl_vicreg.md +25 -30
- pysits-2.0.0.dev3/pysits/docs/content/sits_stats.md +20 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_stratified_sampling.md +9 -8
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_svm.md +11 -10
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_tae.md +1 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_tempcnn.md +13 -9
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_texture.md +9 -7
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_tiles_to_roi.md +4 -4
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_timeline.md +4 -3
- pysits-2.0.0.dev3/pysits/docs/content/sits_timeseries_to_csv.md +23 -0
- pysits-2.0.0.dev3/pysits/docs/content/sits_to_csv.md +22 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_to_xlsx.md +7 -7
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_tuning.md +2 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_tuning_hparams.md +2 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_uncertainty_sampling.md +7 -5
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_validate.md +3 -3
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_variance.md +7 -7
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_view.md +9 -12
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_xgboost.md +8 -8
- pysits-2.0.0.dev3/pysits/docs/content/summary.md +42 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/frame.py +16 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/data.py +30 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/exporters/__init__.py +2 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/exporters/files.py +6 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/ml.py +10 -6
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/ts.py +12 -6
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/visualization.py +9 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/visualization/base.py +8 -1
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/conftest.py +48 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_classification.py +13 -14
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_cube.py +57 -12
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_data.py +7 -27
- pysits-2.0.0.dev3/tests/test_embedding.py +251 -0
- pysits-2.0.0.dev3/tests/test_exporters.py +96 -0
- pysits-2.0.0.dev1/tests/test_geopandas.py → pysits-2.0.0.dev3/tests/test_exporters_geopandas.py +3 -17
- pysits-2.0.0.dev1/tests/test_xarray.py → pysits-2.0.0.dev3/tests/test_exporters_xarray.py +14 -27
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_ml_models.py +41 -2
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_rl_models.py +36 -0
- pysits-2.0.0.dev3/tests/test_som.py +103 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_visualization.py +87 -19
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/uv.lock +182 -24
- pysits-2.0.0.dev1/pysits/docs/content/impute_mean.md +0 -9
- pysits-2.0.0.dev1/pysits/docs/content/plot.md +0 -112
- pysits-2.0.0.dev1/pysits/docs/content/sits_accuracy_summary.md +0 -11
- pysits-2.0.0.dev1/pysits/docs/content/sits_as_geopandas.md +0 -28
- pysits-2.0.0.dev1/pysits/docs/content/sits_classify.md +0 -107
- pysits-2.0.0.dev1/pysits/docs/content/sits_config.md +0 -28
- pysits-2.0.0.dev1/pysits/docs/content/sits_cube.md +0 -97
- pysits-2.0.0.dev1/pysits/docs/content/sits_get_data.md +0 -80
- pysits-2.0.0.dev1/pysits/docs/content/sits_lightgbm.md +0 -42
- pysits-2.0.0.dev1/pysits/docs/content/sits_parallel.md +0 -38
- pysits-2.0.0.dev1/pysits/docs/content/sits_pred_features.md +0 -21
- pysits-2.0.0.dev1/pysits/docs/content/sits_reduce.md +0 -63
- pysits-2.0.0.dev1/pysits/docs/content/sits_sample.md +0 -27
- pysits-2.0.0.dev1/pysits/docs/content/sits_stats.md +0 -21
- pysits-2.0.0.dev1/pysits/docs/content/sits_to_csv.md +0 -23
- pysits-2.0.0.dev1/pysits/docs/content/summary.md +0 -36
- pysits-2.0.0.dev1/pysits/sits/classification.py +0 -42
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/.gitattributes +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/.github/workflows/ruff.yaml +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/.gitignore +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/.pre-commit-config.yaml +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/LICENSE +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/README.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/conda/meta.yaml +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/backend/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/backend/functions.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/backend/loaders.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/clojure.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/common.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/decorators.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/dsl/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/dsl/base.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/dsl/mask.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/dsl/tuning.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/stac.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/vector.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/conversions/xarray.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_bands.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_clean.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_cluster_clean.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_colors.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_colors_reset.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_colors_set.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_config_show.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_formula_linear.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_pred_references.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_rfor.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_som_clean_samples.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_train.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/content/sits_uncertainty.md +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/docs/decorators.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/extras/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/extras/earthdatalogin.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/extras/torch.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/jinja.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/base.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/accuracy.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/base.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/cube.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/frame_accessor.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/matrix.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/table.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/ts.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/tuning.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/data/vector.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/frame.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/ml.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/models/resolver.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/settings.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/colors.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/config.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/context.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/cube.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/exporters/sf.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/exporters/xarray.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/impute.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/segment.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/tiles.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/tuning.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/sits/utils.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/templates/cube.html +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/templates/tuning.html +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/visualization/__init__.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/visualization/image.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/visualization/leaflet.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/pysits/visualization/tmap.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_config.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_conversions.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_dsl.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_extras.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_indexing.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_resolver.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_tiles.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_tuning.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_utils.py +0 -0
- {pysits-2.0.0.dev1 → pysits-2.0.0.dev3}/tests/test_validation.py +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(R --version)",
|
|
5
|
+
"Bash(pyenv versions *)",
|
|
6
|
+
"Bash(pyenv install *)",
|
|
7
|
+
"Bash(grep -E \"^ 3\\\\.\\(10|11|12|13|14\\)\\\\.[0-9]+$\")",
|
|
8
|
+
"Bash(chmod +x run_matrix.sh)",
|
|
9
|
+
"Bash(./run_matrix.sh /Users/felipecarlos/.pyenv/versions/3.12.13/bin/python3 3.12)",
|
|
10
|
+
"Bash(Rscript *)"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"disabledMcpjsonServers": [
|
|
14
|
+
"geo-infrastructure"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
reason:
|
|
7
|
+
required: false
|
|
8
|
+
description: 'Reason'
|
|
9
|
+
default: 'Manual trigger'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Python ${{ matrix.python-version }}
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
strategy:
|
|
17
|
+
# Report every version, so a single break does not hide the others.
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
21
|
+
|
|
22
|
+
env:
|
|
23
|
+
# Fail the build on R warnings that would otherwise pass unnoticed
|
|
24
|
+
R_KEEP_PKG_SOURCE: yes
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout code
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up R
|
|
31
|
+
uses: r-lib/actions/setup-r@v2
|
|
32
|
+
with:
|
|
33
|
+
use-public-rspm: true
|
|
34
|
+
|
|
35
|
+
- name: Install R dependencies
|
|
36
|
+
uses: r-lib/actions/setup-r-dependencies@v2
|
|
37
|
+
with:
|
|
38
|
+
# `arrow` and `kohonen` are required by pysits but are not part of a
|
|
39
|
+
# default `install.packages("sits")`, so they are listed explicitly.
|
|
40
|
+
packages: |
|
|
41
|
+
any::sits
|
|
42
|
+
any::arrow
|
|
43
|
+
any::kohonen
|
|
44
|
+
any::jsonlite
|
|
45
|
+
|
|
46
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
47
|
+
uses: actions/setup-python@v5
|
|
48
|
+
with:
|
|
49
|
+
python-version: ${{ matrix.python-version }}
|
|
50
|
+
|
|
51
|
+
- name: Create a clean virtual environment
|
|
52
|
+
# Mirrors how users install pysits, so a broken dependency resolution
|
|
53
|
+
# is caught here rather than by them.
|
|
54
|
+
run: python -m venv .venv
|
|
55
|
+
|
|
56
|
+
- name: Install pysits
|
|
57
|
+
# `--only-binary` makes pip fail instead of falling back to a source
|
|
58
|
+
# build when no wheel matches this interpreter. Those builds have
|
|
59
|
+
# shipped binaries that segfault. Only pysits itself is built here.
|
|
60
|
+
run: |
|
|
61
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
62
|
+
.venv/bin/python -m pip install \
|
|
63
|
+
--only-binary=:all: --no-binary pysits \
|
|
64
|
+
".[dev]"
|
|
65
|
+
|
|
66
|
+
- name: Report resolved dependency versions
|
|
67
|
+
run: .venv/bin/python -m pip list
|
|
68
|
+
|
|
69
|
+
- name: Verify Arrow interoperability between R and Python
|
|
70
|
+
# pyarrow and R arrow package each bundle libarrow. If they stop
|
|
71
|
+
# sharing an allocator, transfers are silently corrupted rather than
|
|
72
|
+
# failing, so this asserts a known value survives a round-trip.
|
|
73
|
+
run: |
|
|
74
|
+
.venv/bin/python - <<'EOF'
|
|
75
|
+
import pyarrow as pa
|
|
76
|
+
|
|
77
|
+
import pysits
|
|
78
|
+
from pysits.conversions.tibble import (
|
|
79
|
+
pandas_sits_to_tibble,
|
|
80
|
+
tibble_sits_to_pandas,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
probe = [0.5, 1.5, 2.5]
|
|
84
|
+
assert pa.array(probe).to_pylist() == probe, "pyarrow returns corrupted data"
|
|
85
|
+
|
|
86
|
+
samples = pysits.samples_modis_ndvi
|
|
87
|
+
expected = samples["time_series"][0]["NDVI"].tolist()
|
|
88
|
+
actual = tibble_sits_to_pandas(pandas_sits_to_tibble(samples.head(1)))
|
|
89
|
+
actual = actual["time_series"][0]["NDVI"].tolist()
|
|
90
|
+
|
|
91
|
+
assert actual == expected, f"round-trip corrupted data: {actual} != {expected}"
|
|
92
|
+
print("Arrow round-trip is lossless.")
|
|
93
|
+
EOF
|
|
94
|
+
|
|
95
|
+
- name: Run tests
|
|
96
|
+
run: .venv/bin/python -m pytest
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pysits
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev3
|
|
4
4
|
Summary: Python wrapper for the sits R package
|
|
5
5
|
Project-URL: Homepage, https://github.com/e-sensing/pysits
|
|
6
6
|
Project-URL: Issue Tracker, https://github.com/e-sensing/pysits/issues
|
|
@@ -20,17 +20,26 @@ Requires-Dist: geopandas>=1.1.0
|
|
|
20
20
|
Requires-Dist: jinja2>=3.1.6
|
|
21
21
|
Requires-Dist: matplotlib>=3.10.1
|
|
22
22
|
Requires-Dist: pandas>=2.2.3
|
|
23
|
+
Requires-Dist: pandas>=2.3.3; python_version >= '3.14'
|
|
23
24
|
Requires-Dist: pillow>=11.1.0
|
|
24
25
|
Requires-Dist: pyarrow>=20.0.0
|
|
25
|
-
Requires-Dist: rpy2<4.0.0,>=3.
|
|
26
|
+
Requires-Dist: rpy2<4.0.0,>=3.6.0
|
|
26
27
|
Requires-Dist: shapely>=2.1.1
|
|
27
28
|
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: affine>=2.4.0; extra == 'dev'
|
|
28
30
|
Requires-Dist: cloudpickle>=3.1.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: dask>=2025.3.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: odc-stac>=0.5.3; extra == 'dev'
|
|
33
|
+
Requires-Dist: planetary-computer>=1.0.0; extra == 'dev'
|
|
29
34
|
Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pystac>=1.15.0; extra == 'dev'
|
|
30
36
|
Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
|
|
31
37
|
Requires-Dist: pytest-randomly>=3.16.0; extra == 'dev'
|
|
32
38
|
Requires-Dist: pytest>=7.4.4; extra == 'dev'
|
|
39
|
+
Requires-Dist: rasterio>=1.3.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: rioxarray>=0.18.2; extra == 'dev'
|
|
33
41
|
Requires-Dist: ruff>=0.11.12; extra == 'dev'
|
|
42
|
+
Requires-Dist: xarray>=2025.3.0; extra == 'dev'
|
|
34
43
|
Provides-Extra: xarray
|
|
35
44
|
Requires-Dist: affine>=2.4.0; extra == 'xarray'
|
|
36
45
|
Requires-Dist: dask>=2025.3.0; extra == 'xarray'
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
[project]
|
|
19
19
|
name = "pysits"
|
|
20
|
-
version = "2.0.0.
|
|
20
|
+
version = "2.0.0.dev3"
|
|
21
21
|
description = "Python wrapper for the sits R package"
|
|
22
22
|
readme = "README.md"
|
|
23
23
|
requires-python = ">=3.10,<4"
|
|
@@ -58,8 +58,13 @@ classifiers = [
|
|
|
58
58
|
]
|
|
59
59
|
|
|
60
60
|
dependencies = [
|
|
61
|
-
|
|
61
|
+
# 3.6.0 is the first release distributing wheels. Earlier ones are
|
|
62
|
+
# source-only, so pip would compile rpy2 against the local R installation
|
|
63
|
+
"rpy2>=3.6.0,<4.0.0",
|
|
62
64
|
"pandas>=2.2.3",
|
|
65
|
+
# pandas ships no wheels for Python 3.14 before 2.3.3. Without this floor
|
|
66
|
+
# pip builds pandas from source there, and the result segfaults.
|
|
67
|
+
"pandas>=2.3.3; python_version>='3.14'",
|
|
63
68
|
"pillow>=11.1.0",
|
|
64
69
|
"matplotlib>=3.10.1",
|
|
65
70
|
"geopandas>=1.1.0",
|
|
@@ -90,6 +95,9 @@ dev = [
|
|
|
90
95
|
"pytest-cov>=6.1.1",
|
|
91
96
|
"pytest-randomly>=3.16.0",
|
|
92
97
|
"cloudpickle>=3.1.1",
|
|
98
|
+
# The test suite covers the xarray exporters and reads rasters directly
|
|
99
|
+
"pysits[xarray]",
|
|
100
|
+
"rasterio>=1.3.0",
|
|
93
101
|
]
|
|
94
102
|
|
|
95
103
|
[tool.ruff]
|
|
@@ -17,10 +17,13 @@
|
|
|
17
17
|
|
|
18
18
|
"""pysits module."""
|
|
19
19
|
|
|
20
|
+
# Importing `backend.arrow` first selects the libarrow allocator, which must
|
|
21
|
+
# happen before anything imports `pyarrow` or loads the R `arrow` package.
|
|
22
|
+
# Keep this import above the others. See `pysits.backend.arrow`.
|
|
23
|
+
from .backend import arrow as _arrow # noqa: F401
|
|
20
24
|
from .conversions.dsl.mask import MaskValue
|
|
21
25
|
from .conversions.dsl.tuning import hparam
|
|
22
26
|
from .settings import __version__
|
|
23
|
-
from .sits.classification import sits_classify, sits_label_classification, sits_smooth
|
|
24
27
|
from .sits.colors import (
|
|
25
28
|
sits_colors,
|
|
26
29
|
sits_colors_reset,
|
|
@@ -62,6 +65,9 @@ from .sits.data import (
|
|
|
62
65
|
sits_apply,
|
|
63
66
|
sits_bands,
|
|
64
67
|
sits_bbox,
|
|
68
|
+
sits_classify,
|
|
69
|
+
sits_encode,
|
|
70
|
+
sits_label_classification,
|
|
65
71
|
sits_labels,
|
|
66
72
|
sits_labels_summary,
|
|
67
73
|
sits_list_collections,
|
|
@@ -69,10 +75,17 @@ from .sits.data import (
|
|
|
69
75
|
sits_mixture_model,
|
|
70
76
|
sits_reduce,
|
|
71
77
|
sits_select,
|
|
78
|
+
sits_smooth,
|
|
72
79
|
sits_timeline,
|
|
73
80
|
)
|
|
74
81
|
from .sits.data import sits_summary as summary
|
|
75
|
-
from .sits.exporters import
|
|
82
|
+
from .sits.exporters import (
|
|
83
|
+
sits_as_geopandas,
|
|
84
|
+
sits_as_xarray,
|
|
85
|
+
sits_timeseries_to_csv,
|
|
86
|
+
sits_to_csv,
|
|
87
|
+
sits_to_xlsx,
|
|
88
|
+
)
|
|
76
89
|
from .sits.impute import (
|
|
77
90
|
impute_linear,
|
|
78
91
|
impute_mean,
|
|
@@ -87,6 +100,7 @@ from .sits.ml import (
|
|
|
87
100
|
sits_kfold_validate,
|
|
88
101
|
sits_lightgbm,
|
|
89
102
|
sits_lighttae,
|
|
103
|
+
sits_lstm_fcn,
|
|
90
104
|
sits_mlp,
|
|
91
105
|
sits_model_export,
|
|
92
106
|
sits_pre_train,
|
|
@@ -107,7 +121,6 @@ from .sits.ts import (
|
|
|
107
121
|
sits_cluster_clean,
|
|
108
122
|
sits_cluster_dendro,
|
|
109
123
|
sits_cluster_frequency,
|
|
110
|
-
sits_encode,
|
|
111
124
|
sits_geo_dist,
|
|
112
125
|
sits_get_class,
|
|
113
126
|
sits_get_data,
|
|
@@ -118,6 +131,7 @@ from .sits.ts import (
|
|
|
118
131
|
sits_pred_references,
|
|
119
132
|
sits_pred_sample,
|
|
120
133
|
sits_predictors,
|
|
134
|
+
sits_random_sampling,
|
|
121
135
|
sits_reduce_imbalance,
|
|
122
136
|
sits_sample,
|
|
123
137
|
sits_sampling_design,
|
|
@@ -125,6 +139,7 @@ from .sits.ts import (
|
|
|
125
139
|
sits_som_clean_samples,
|
|
126
140
|
sits_som_evaluate_cluster,
|
|
127
141
|
sits_som_map,
|
|
142
|
+
sits_som_remove_samples,
|
|
128
143
|
sits_stats,
|
|
129
144
|
sits_stratified_sampling,
|
|
130
145
|
sits_validate,
|
|
@@ -137,13 +152,21 @@ from .sits.utils import (
|
|
|
137
152
|
read_rds,
|
|
138
153
|
)
|
|
139
154
|
from .sits.visualization import sits_plot as plot
|
|
140
|
-
from .sits.visualization import sits_view
|
|
155
|
+
from .sits.visualization import sits_sankey, sits_view
|
|
141
156
|
|
|
142
157
|
__all__ = (
|
|
143
158
|
# Classification
|
|
144
159
|
"sits_classify",
|
|
145
160
|
"sits_smooth",
|
|
146
161
|
"sits_label_classification",
|
|
162
|
+
# Embeddings
|
|
163
|
+
"sits_pre_train",
|
|
164
|
+
"sits_encode",
|
|
165
|
+
"sits_ssl_mae",
|
|
166
|
+
"sits_ssl_lejepa",
|
|
167
|
+
"sits_ssl_vicreg",
|
|
168
|
+
"sits_barlow_twins",
|
|
169
|
+
"sits_contrastive_learning",
|
|
147
170
|
# Cube
|
|
148
171
|
"sits_cube",
|
|
149
172
|
"sits_clean",
|
|
@@ -170,7 +193,7 @@ __all__ = (
|
|
|
170
193
|
"sits_config_user_file",
|
|
171
194
|
"sits_config_value",
|
|
172
195
|
"sits_parallel",
|
|
173
|
-
# Data
|
|
196
|
+
# Data
|
|
174
197
|
"sits_bands",
|
|
175
198
|
"sits_timeline",
|
|
176
199
|
"sits_labels",
|
|
@@ -194,6 +217,7 @@ __all__ = (
|
|
|
194
217
|
"sits_resnet",
|
|
195
218
|
"sits_tempcnn",
|
|
196
219
|
"sits_lighttae",
|
|
220
|
+
"sits_lstm_fcn",
|
|
197
221
|
"sits_svm",
|
|
198
222
|
"sits_xgboost",
|
|
199
223
|
"sits_lightgbm",
|
|
@@ -202,12 +226,6 @@ __all__ = (
|
|
|
202
226
|
"sits_model_export",
|
|
203
227
|
"sits_formula_linear",
|
|
204
228
|
"sits_formula_logref",
|
|
205
|
-
"sits_ssl_mae",
|
|
206
|
-
"sits_ssl_lejepa",
|
|
207
|
-
"sits_ssl_vicreg",
|
|
208
|
-
"sits_barlow_twins",
|
|
209
|
-
"sits_contrastive_learning",
|
|
210
|
-
"sits_pre_train",
|
|
211
229
|
# Impute
|
|
212
230
|
"impute_linear",
|
|
213
231
|
"impute_mean",
|
|
@@ -228,13 +246,14 @@ __all__ = (
|
|
|
228
246
|
"sits_som_map",
|
|
229
247
|
"sits_som_evaluate_cluster",
|
|
230
248
|
"sits_som_clean_samples",
|
|
249
|
+
"sits_som_remove_samples",
|
|
231
250
|
"sits_geo_dist",
|
|
232
251
|
"sits_patterns",
|
|
233
252
|
"sits_sample",
|
|
234
253
|
"sits_reduce_imbalance",
|
|
235
254
|
"sits_sampling_design",
|
|
236
255
|
"sits_stratified_sampling",
|
|
237
|
-
"
|
|
256
|
+
"sits_random_sampling",
|
|
238
257
|
# Tiles
|
|
239
258
|
"sits_tiles_to_roi",
|
|
240
259
|
"sits_roi_to_tiles",
|
|
@@ -249,12 +268,14 @@ __all__ = (
|
|
|
249
268
|
"sits_as_xarray",
|
|
250
269
|
"sits_as_geopandas",
|
|
251
270
|
"sits_to_xlsx",
|
|
271
|
+
"sits_timeseries_to_csv",
|
|
252
272
|
# Tuning
|
|
253
273
|
"sits_tuning_hparams",
|
|
254
274
|
"sits_tuning",
|
|
255
275
|
# Visualization
|
|
256
276
|
"plot",
|
|
257
277
|
"sits_view",
|
|
278
|
+
"sits_sankey",
|
|
258
279
|
# DSL Variables
|
|
259
280
|
"MaskValue",
|
|
260
281
|
"hparam",
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2025 sits developers.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify it
|
|
5
|
+
# under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
"""Arrow interoperability between R and Python.
|
|
19
|
+
|
|
20
|
+
``pysits`` moves data between R and Python as Arrow IPC streams. That puts two
|
|
21
|
+
independent builds of the libarrow C++ library in a single process: the one
|
|
22
|
+
bundled in the R ``arrow`` package and the one bundled in ``pyarrow``. Their
|
|
23
|
+
symbols collapse into a single namespace, so a call made through ``pyarrow``
|
|
24
|
+
can be served by R's libarrow.
|
|
25
|
+
|
|
26
|
+
Each build keeps a private ``mimalloc`` heap. When the two are mixed, a buffer
|
|
27
|
+
allocated by one library is read back as zeroed memory by the other, and every
|
|
28
|
+
transfer is silently corrupted instead of failing. Both builds also support the
|
|
29
|
+
system allocator, which is shared, so selecting it keeps them interoperable.
|
|
30
|
+
|
|
31
|
+
The allocator is chosen by libarrow the first time it initializes, so importing
|
|
32
|
+
this module sets ``ARROW_DEFAULT_MEMORY_POOL``. It is imported before anything
|
|
33
|
+
that pulls in ``pyarrow`` or the R ``arrow`` package.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
import os
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Allocator selected to keep R libarrow and pyarrow interoperable
|
|
40
|
+
#
|
|
41
|
+
ARROW_MEMORY_POOL_ENVVAR = "ARROW_DEFAULT_MEMORY_POOL"
|
|
42
|
+
ARROW_MEMORY_POOL = "system"
|
|
43
|
+
|
|
44
|
+
# Set on import: libarrow reads this once, when it initializes. A value already
|
|
45
|
+
# present in the environment is left alone so users can override it.
|
|
46
|
+
os.environ.setdefault(ARROW_MEMORY_POOL_ENVVAR, ARROW_MEMORY_POOL)
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Values transferred to R and back to verify the round-trip is lossless. A
|
|
50
|
+
# mismatched pair of libarrow builds reads them back as zeros.
|
|
51
|
+
#
|
|
52
|
+
PROBE_COLUMN = "pysits_arrow_probe"
|
|
53
|
+
PROBE_VALUES = [0.5, 1.5, 2.5]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def check_arrow_memory_pool() -> None:
|
|
57
|
+
"""Refuse to load R ``arrow`` package under an unshared allocator.
|
|
58
|
+
|
|
59
|
+
Called before the R ``arrow`` package is loaded. Corruption appears only
|
|
60
|
+
once both libarrow builds are in use, and is silent when it does, so the
|
|
61
|
+
configuration is rejected up front rather than probed for afterwards.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
RuntimeError: If the selected allocator is not the shared one.
|
|
65
|
+
"""
|
|
66
|
+
selected = os.environ.get(ARROW_MEMORY_POOL_ENVVAR)
|
|
67
|
+
|
|
68
|
+
if selected == ARROW_MEMORY_POOL:
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
raise RuntimeError(
|
|
72
|
+
f"{ARROW_MEMORY_POOL_ENVVAR} is set to '{selected}', but pysits "
|
|
73
|
+
f"requires '{ARROW_MEMORY_POOL}'.\n\n"
|
|
74
|
+
"The R `arrow` package and `pyarrow` each bundle their own build of "
|
|
75
|
+
"the libarrow C++ library. Loaded together, they must use the system "
|
|
76
|
+
"allocator to share buffers. With any other allocator, data sent "
|
|
77
|
+
"between R and Python is silently replaced by zeros.\n\n"
|
|
78
|
+
f"Unset {ARROW_MEMORY_POOL_ENVVAR}, or set it before starting Python:\n\n"
|
|
79
|
+
f" export {ARROW_MEMORY_POOL_ENVVAR}={ARROW_MEMORY_POOL}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def arrow_interop_error(observed: list) -> RuntimeError:
|
|
84
|
+
"""Build the error raised when an Arrow round-trip loses data.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
observed (list): Values read back from R for `PROBE_VALUES`.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
RuntimeError: Error describing the cause and how to resolve it.
|
|
91
|
+
"""
|
|
92
|
+
import pyarrow as pa
|
|
93
|
+
|
|
94
|
+
pool = pa.default_memory_pool().backend_name
|
|
95
|
+
|
|
96
|
+
return RuntimeError(
|
|
97
|
+
"Data sent to R is coming back corrupted, so pysits cannot run.\n\n"
|
|
98
|
+
f"Sent {PROBE_VALUES}, received {observed}.\n\n"
|
|
99
|
+
"The R `arrow` package and `pyarrow` each bundle their own build of "
|
|
100
|
+
"the libarrow C++ library. Loaded together, they must use the system "
|
|
101
|
+
f"allocator to share buffers, but pyarrow is using '{pool}'.\n\n"
|
|
102
|
+
"This happens when pyarrow is initialized before pysits with a "
|
|
103
|
+
"different allocator. Either import pysits before pyarrow, or set the "
|
|
104
|
+
"environment variable before starting Python:\n\n"
|
|
105
|
+
f" export {ARROW_MEMORY_POOL_ENVVAR}={ARROW_MEMORY_POOL}"
|
|
106
|
+
)
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
"""backend packages."""
|
|
19
19
|
|
|
20
|
+
from pysits.backend.arrow import check_arrow_memory_pool
|
|
20
21
|
from pysits.backend.loaders import load_package
|
|
21
22
|
from pysits.settings import __sitsver__
|
|
22
23
|
|
|
@@ -33,4 +34,9 @@ r_pkg_leaflet = load_package("leaflet")
|
|
|
33
34
|
r_pkg_kohonen = load_package("kohonen")
|
|
34
35
|
r_pkg_sf = load_package("sf")
|
|
35
36
|
r_pkg_htmlwidgets = load_package("htmlwidgets")
|
|
37
|
+
|
|
38
|
+
# `arrow` brings a second libarrow build into the process, so the allocator has
|
|
39
|
+
# to be compatible before it is loaded. See `pysits.backend.arrow`.
|
|
40
|
+
check_arrow_memory_pool()
|
|
41
|
+
|
|
36
42
|
r_pkg_arrow = load_package("arrow")
|
|
@@ -36,6 +36,7 @@ from rpy2.robjects.conversion import localconverter
|
|
|
36
36
|
from rpy2.robjects.vectors import DataFrame as RDataFrame
|
|
37
37
|
from shapely import wkt
|
|
38
38
|
|
|
39
|
+
from pysits.backend.arrow import PROBE_COLUMN, PROBE_VALUES, arrow_interop_error
|
|
39
40
|
from pysits.backend.functions import r_fnc_class, r_fnc_set_column
|
|
40
41
|
from pysits.backend.pkgs import r_pkg_base, r_pkg_sf, r_pkg_sits
|
|
41
42
|
from pysits.models.frame import NestedFrame
|
|
@@ -90,6 +91,39 @@ def _sf_to_shapely(sf_object: RDataFrame) -> list:
|
|
|
90
91
|
#
|
|
91
92
|
# Arrow IPC helpers
|
|
92
93
|
#
|
|
94
|
+
def _check_arrow_interop() -> None:
|
|
95
|
+
"""Verify that Arrow data is not corrupted once R's libarrow is loaded.
|
|
96
|
+
|
|
97
|
+
R libarrow only initializes on first use, so a probe is sent through R to
|
|
98
|
+
force it, and ``pyarrow`` is then re-tested. A mismatched pair of libarrow
|
|
99
|
+
builds corrupts the conversion of Python objects to Arrow arrays, returning
|
|
100
|
+
zeros instead of raising, which would silently damage every nested column.
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
RuntimeError: If either transfer loses data.
|
|
104
|
+
"""
|
|
105
|
+
probe = PandasDataFrame({PROBE_COLUMN: PROBE_VALUES})
|
|
106
|
+
|
|
107
|
+
# Forces R libarrow to initialize, and checks the Python -> R direction
|
|
108
|
+
r_probe = rpy2_globalenv["pysits_read_ipc_raw"](
|
|
109
|
+
robjects.vectors.ByteVector(_dataframe_to_ipc_bytes(probe))
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Load content from R
|
|
113
|
+
observed = list(r_probe.rx2(PROBE_COLUMN))
|
|
114
|
+
|
|
115
|
+
# If it is different, then given an error
|
|
116
|
+
if observed != PROBE_VALUES:
|
|
117
|
+
raise arrow_interop_error(observed)
|
|
118
|
+
|
|
119
|
+
# Both libarrow builds are live now: check the conversion of Python objects
|
|
120
|
+
# to Arrow arrays, which is the path nested columns depend on.
|
|
121
|
+
observed = pa.array(PROBE_VALUES).to_pylist()
|
|
122
|
+
|
|
123
|
+
if observed != PROBE_VALUES:
|
|
124
|
+
raise arrow_interop_error(observed)
|
|
125
|
+
|
|
126
|
+
|
|
93
127
|
def _ensure_r_ipc_functions():
|
|
94
128
|
"""Define R-side IPC reader/writer/unnester functions once."""
|
|
95
129
|
if "pysits_write_ipc_raw" in rpy2_globalenv:
|
|
@@ -162,6 +196,8 @@ def _ensure_r_ipc_functions():
|
|
|
162
196
|
}
|
|
163
197
|
""")
|
|
164
198
|
|
|
199
|
+
_check_arrow_interop()
|
|
200
|
+
|
|
165
201
|
|
|
166
202
|
def _dataframe_to_ipc_bytes(df: PandasDataFrame) -> bytes:
|
|
167
203
|
"""Serialize a pandas DataFrame to Arrow IPC bytes.
|
|
@@ -480,7 +516,8 @@ def geopandas_to_tibble(data: GeoPandasDataFrame) -> RDataFrame:
|
|
|
480
516
|
f"Warning: Dropping columns with embedded DataFrames: {dropped_columns}"
|
|
481
517
|
)
|
|
482
518
|
|
|
483
|
-
|
|
519
|
+
# Geometries are transferred as WKT, so the result is a plain data frame
|
|
520
|
+
data_safe = PandasDataFrame(data[safe_columns].copy())
|
|
484
521
|
|
|
485
522
|
if isinstance(data, GeoPandasDataFrame):
|
|
486
523
|
geom_col = data.geometry.name
|
|
@@ -3,7 +3,8 @@ Replace NA values by linear interpolation
|
|
|
3
3
|
Remove NA by linear interpolation
|
|
4
4
|
|
|
5
5
|
Args:
|
|
6
|
-
data (list
|
|
6
|
+
data (list): A time series vector or matrix.
|
|
7
7
|
|
|
8
8
|
Returns:
|
|
9
9
|
R: A set of filtered time series using the imputation function.
|
|
10
|
+
|
|
@@ -3,14 +3,14 @@ Remove NA using weighted moving average
|
|
|
3
3
|
Remove NA using weighted moving average
|
|
4
4
|
|
|
5
5
|
Args:
|
|
6
|
-
data (list): A time series vector or matrix.
|
|
6
|
+
data (list[float]): A time series vector or matrix.
|
|
7
7
|
k (int): Width of the moving average window. Expands to both sides
|
|
8
8
|
of the center element e.g. k = 2 means 4 observations (2 left,
|
|
9
9
|
2 right) are taken into account. If all observations in the
|
|
10
10
|
current window are NA, the window size is automatically
|
|
11
11
|
increased until there are at least 2 non-NA values present.
|
|
12
|
-
weighting (str):
|
|
13
|
-
|
|
12
|
+
weighting (str): Weighting strategy to be used. More details below
|
|
13
|
+
(default is "simple").
|
|
14
14
|
|
|
15
15
|
Returns:
|
|
16
16
|
R: A set of filtered time series using the imputation function.
|