pysits 2.0.0.dev8__tar.gz → 2.0.0.dev10__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.dev10/.claude/settings.local.json +7 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/PKG-INFO +1 -1
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pyproject.toml +1 -1
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/__init__.py +10 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/backend/functions.py +3 -0
- pysits-2.0.0.dev10/pysits/docs/content/sits_config_to_hf.md +46 -0
- pysits-2.0.0.dev10/pysits/docs/content/sits_from_hf.md +85 -0
- pysits-2.0.0.dev10/pysits/docs/content/sits_from_parquet.md +26 -0
- pysits-2.0.0.dev10/pysits/docs/content/sits_to_hf.md +76 -0
- pysits-2.0.0.dev10/pysits/docs/content/sits_to_parquet.md +23 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/exporters/__init__.py +13 -1
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/exporters/files.py +30 -0
- pysits-2.0.0.dev10/pysits/sits/exporters/hf.py +74 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_exporters.py +51 -1
- pysits-2.0.0.dev10/tests/test_exporters_hf.py +154 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/uv.lock +1 -1
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/.gitattributes +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/.github/actions/setup-pysits/action.yml +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/.github/workflows/ruff.yaml +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/.github/workflows/tests.yaml +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/.gitignore +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/.pre-commit-config.yaml +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/LICENSE +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/README.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/conda/meta.yaml +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/backend/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/backend/arrow.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/backend/loaders.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/backend/pkgs.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/backend/rinterface.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/clojure.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/common.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/decorators.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/dsl/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/dsl/base.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/dsl/mask.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/dsl/tuning.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/stac.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/tibble.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/vector.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/conversions/xarray.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/impute_linear.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/impute_mean.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/impute_mean_window.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/impute_median.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/plot.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_accuracy.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_accuracy_summary.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_add_base_cube.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_apply.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_as_geopandas.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_bands.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_barlow_twins.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_bbox.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_classify.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_clean.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_cluster_clean.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_cluster_dendro.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_cluster_frequency.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_colors.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_colors_qgis.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_colors_reset.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_colors_set.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_colors_show.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_combine_predictions.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_confidence_sampling.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_config.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_config_show.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_config_user_file.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_contrastive_learning.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_cube.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_cube_copy.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_encode.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_formula_linear.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_formula_logref.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_geo_dist.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_get_class.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_get_data.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_get_probs.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_kfold_validate.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_label_classification.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_labels.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_labels_summary.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_lightgbm.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_lighttae.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_list_collections.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_lstm_fcn.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_merge.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_mixture_model.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_mlp.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_model_export.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_mosaic.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_parallel.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_patterns.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_pre_train.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_pred_features.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_pred_normalize.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_pred_references.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_pred_sample.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_predictors.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_random_sampling.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_reclassify.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_reduce.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_reduce_imbalance.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_regularize.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_resnet.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_rfor.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_roi_to_tiles.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_sample.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_sampling_design.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_sankey.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_segment.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_select.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_show_prediction.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_slic.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_smooth.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_snic.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_som_clean_samples.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_som_evaluate_cluster.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_som_map.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_som_remove_samples.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_ssl_lejepa.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_ssl_mae.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_ssl_vicreg.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_stats.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_stratified_sampling.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_svm.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_tae.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_tempcnn.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_texture.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_tiles_to_roi.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_timeline.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_timeseries_to_csv.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_to_csv.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_to_xlsx.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_train.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_tuning.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_tuning_hparams.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_uncertainty.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_uncertainty_sampling.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_validate.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_variance.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_view.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/sits_xgboost.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/content/summary.md +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/docs/decorators.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/extras/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/extras/earthdatalogin.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/extras/torch.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/jinja.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/base.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/accuracy.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/base.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/cube.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/frame.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/frame_accessor.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/matrix.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/table.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/ts.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/tuning.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/data/vector.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/frame.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/ml.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/resolver.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/models/visual.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/network.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/settings.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/colors.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/config.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/context.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/cube.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/data.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/exporters/sf.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/exporters/xarray.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/impute.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/ml.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/segment.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/tiles.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/ts.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/tuning.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/utils.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/sits/visualization.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/templates/cube.html +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/templates/plot.html +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/templates/tuning.html +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/visualization/__init__.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/visualization/base.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/visualization/device.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/visualization/host.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/visualization/leaflet.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/pysits/visualization/options.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/conftest.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_backend.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_classification.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_config.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_conversions.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_cube.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_data.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_dsl.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_embedding.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_exporters_geopandas.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_exporters_xarray.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_extras.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_indexing.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_ml_models.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_network.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_resolver.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_rl_models.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_som.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_tiles.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_tuning.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_utils.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_validation.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_visual_models.py +0 -0
- {pysits-2.0.0.dev8 → pysits-2.0.0.dev10}/tests/test_visualization.py +0 -0
|
@@ -87,8 +87,13 @@ from .sits.data import sits_summary as summary
|
|
|
87
87
|
from .sits.exporters import (
|
|
88
88
|
sits_as_geopandas,
|
|
89
89
|
sits_as_xarray,
|
|
90
|
+
sits_config_to_hf,
|
|
91
|
+
sits_from_hf,
|
|
92
|
+
sits_from_parquet,
|
|
90
93
|
sits_timeseries_to_csv,
|
|
91
94
|
sits_to_csv,
|
|
95
|
+
sits_to_hf,
|
|
96
|
+
sits_to_parquet,
|
|
92
97
|
sits_to_xlsx,
|
|
93
98
|
)
|
|
94
99
|
from .sits.impute import (
|
|
@@ -276,6 +281,11 @@ __all__ = (
|
|
|
276
281
|
"sits_as_geopandas",
|
|
277
282
|
"sits_to_xlsx",
|
|
278
283
|
"sits_timeseries_to_csv",
|
|
284
|
+
"sits_to_parquet",
|
|
285
|
+
"sits_from_parquet",
|
|
286
|
+
"sits_to_hf",
|
|
287
|
+
"sits_from_hf",
|
|
288
|
+
"sits_config_to_hf",
|
|
279
289
|
# Tuning
|
|
280
290
|
"sits_tuning_hparams",
|
|
281
291
|
"sits_tuning",
|
|
@@ -58,5 +58,8 @@ r_fnc_colnames = load_function_from_package("base::colnames")
|
|
|
58
58
|
# Base - rownames (base)
|
|
59
59
|
r_fnc_rownames = load_function_from_package("base::rownames")
|
|
60
60
|
|
|
61
|
+
# Base - unname (base)
|
|
62
|
+
r_fnc_unname = load_function_from_package("base::unname")
|
|
63
|
+
|
|
61
64
|
# sits - configuration (internal)
|
|
62
65
|
r_fnc_sits_conf = load_internal_function_from_package("sits:::.conf")
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Describe a collection of sits as a HuggingFace dataset
|
|
2
|
+
|
|
3
|
+
Data cubes shared on HuggingFace are described by a "sits/sits.yml" file
|
|
4
|
+
in the dataset repository, which sits reads to open the dataset.
|
|
5
|
+
|
|
6
|
+
This function writes that description from a collection registered in
|
|
7
|
+
sits (see `sits_list_collections`), which is useful when a dataset shares
|
|
8
|
+
images of a known collection (e.g., images of "SENTINEL-2-L2A" downloaded
|
|
9
|
+
from "MPC").
|
|
10
|
+
|
|
11
|
+
The description of a collection is written as the dataset needs it: the
|
|
12
|
+
bands are named as sits names them in the images, and the properties used
|
|
13
|
+
by sits to reach the provider are not written, as sits defines them when
|
|
14
|
+
it registers a dataset.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
source (str): Data source.
|
|
18
|
+
|
|
19
|
+
collection (str): Image collection.
|
|
20
|
+
|
|
21
|
+
bands (list[str]): Bands shared in the dataset (default is all of
|
|
22
|
+
them).
|
|
23
|
+
|
|
24
|
+
output_dir (str | pathlib.Path): Existing directory where the file
|
|
25
|
+
"sits/sits.yml" is written (optional). When not informed, the
|
|
26
|
+
collection definition is only returned.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
SITStructureData: Collection definition of the dataset.
|
|
30
|
+
|
|
31
|
+
Note:
|
|
32
|
+
A dataset must describe only the bands it holds, and the resolution of
|
|
33
|
+
each band is the one the collection declares. If you need to describe
|
|
34
|
+
a regularized cube, or a cube with custom bands, use `sits_to_hf`.
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
import tempfile
|
|
38
|
+
from pysits import *
|
|
39
|
+
|
|
40
|
+
# describe a collection as a HuggingFace dataset
|
|
41
|
+
sits_config_to_hf(
|
|
42
|
+
source="MPC",
|
|
43
|
+
collection="SENTINEL-2-L2A",
|
|
44
|
+
bands=["B02", "B03", "B04", "B08"],
|
|
45
|
+
output_dir=tempfile.gettempdir(),
|
|
46
|
+
)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Read data cubes, samples and models shared on HuggingFace
|
|
2
|
+
|
|
3
|
+
Reads data shared in a HuggingFace repository. The content of the
|
|
4
|
+
repository defines what is read:
|
|
5
|
+
|
|
6
|
+
- data cubes: datasets describing a collection in a "sits/sits.yml" file
|
|
7
|
+
(see `sits_to_hf`). The images selected are downloaded to `output_dir`
|
|
8
|
+
and a local data cube is returned;
|
|
9
|
+
|
|
10
|
+
- samples: time series saved as ".rds" or ".parquet" files (see
|
|
11
|
+
`sits_to_parquet`);
|
|
12
|
+
|
|
13
|
+
- models: models trained by `sits_train` and saved as ".rds" files.
|
|
14
|
+
|
|
15
|
+
When `file` is not informed, a repository with a "sits/sits.yml" file is
|
|
16
|
+
read as a data cube. Otherwise, the repository must have a single ".rds"
|
|
17
|
+
or ".parquet" file. When there are many, choose one using `file`.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
repo (str): HuggingFace repository ("<user>/<repository>").
|
|
21
|
+
|
|
22
|
+
file (str): File to be read in the repository (optional).
|
|
23
|
+
|
|
24
|
+
type (str): Type of the repository: "dataset" (default) or "model".
|
|
25
|
+
Data cubes are always shared in datasets.
|
|
26
|
+
|
|
27
|
+
bands (list[str]): Bands to be selected in the data cube (optional).
|
|
28
|
+
|
|
29
|
+
tiles (list[str]): Tiles to be selected in the data cube (optional).
|
|
30
|
+
|
|
31
|
+
roi (dict | geopandas.GeoDataFrame): Region of interest to be selected
|
|
32
|
+
in the data cube (optional).
|
|
33
|
+
|
|
34
|
+
crs (str): The Coordinate Reference System (CRS) of the roi.
|
|
35
|
+
|
|
36
|
+
start_date (str): Start date of the data cube ("YYYY-MM-DD").
|
|
37
|
+
|
|
38
|
+
end_date (str): End date of the data cube ("YYYY-MM-DD").
|
|
39
|
+
|
|
40
|
+
output_dir (str | pathlib.Path): Existing directory where the images
|
|
41
|
+
of the data cube are saved (required for data cubes).
|
|
42
|
+
|
|
43
|
+
n_tries (int): Number of attempts to download the same image.
|
|
44
|
+
|
|
45
|
+
multicores (int): Number of cores for parallel downloading.
|
|
46
|
+
|
|
47
|
+
progress (bool): Show progress bar?
|
|
48
|
+
|
|
49
|
+
**kwargs: Other parameters to read data cubes: `labels` (dict) and
|
|
50
|
+
`version` (str) select results produced by sits (e.g.,
|
|
51
|
+
probabilities).
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
SITSCubeModel | SITSTimeSeriesModel | SITSMachineLearningMethod: A data
|
|
55
|
+
cube with local images, a set of samples, or a model.
|
|
56
|
+
|
|
57
|
+
Note:
|
|
58
|
+
HuggingFace limits the number of files a user requests in windows of
|
|
59
|
+
five minutes. For this reason, the images of a data cube are
|
|
60
|
+
downloaded, each one requested only once, in batches that fit the
|
|
61
|
+
requests available. When no request is available, the download waits
|
|
62
|
+
the next window. Images already downloaded in `output_dir` are not
|
|
63
|
+
requested again, so an interrupted download is resumed by calling
|
|
64
|
+
`sits_from_hf` again.
|
|
65
|
+
|
|
66
|
+
To access private repositories, the HuggingFace access token must be
|
|
67
|
+
set in the `HF_TOKEN` environment variable.
|
|
68
|
+
|
|
69
|
+
Examples:
|
|
70
|
+
import tempfile
|
|
71
|
+
from pysits import *
|
|
72
|
+
|
|
73
|
+
# download a data cube shared in a HuggingFace dataset
|
|
74
|
+
cube = sits_from_hf(
|
|
75
|
+
repo="felipemcarlos/sits_mod13q1_sinop",
|
|
76
|
+
output_dir=tempfile.gettempdir(),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# read samples shared in a HuggingFace dataset
|
|
80
|
+
samples = sits_from_hf(repo="felipemcarlos/sits_samples_modis_ndvi")
|
|
81
|
+
|
|
82
|
+
# read a model shared in a HuggingFace model repository
|
|
83
|
+
model = sits_from_hf(
|
|
84
|
+
repo="felipemcarlos/sits_rfor_modis_ndvi", type="model"
|
|
85
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Read sits time series from the Parquet format
|
|
2
|
+
|
|
3
|
+
Reads a file written by `sits_to_parquet` and rebuilds the time series,
|
|
4
|
+
with its class, column order and nested series.
|
|
5
|
+
|
|
6
|
+
Files written by other programs are also read. Their class is then
|
|
7
|
+
inferred from the columns, which must include "longitude", "latitude",
|
|
8
|
+
"start_date", "end_date" and "label".
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
file (str | pathlib.Path): Full path or HTTP(S) URL of the file to
|
|
12
|
+
read (valid file name with extension ".parquet").
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
SITSTimeSeriesModel: Time series.
|
|
16
|
+
|
|
17
|
+
Raises:
|
|
18
|
+
httpx2.HTTPError: If a remote file cannot be downloaded.
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
import tempfile
|
|
22
|
+
from pysits import *
|
|
23
|
+
|
|
24
|
+
parquet_file = tempfile.gettempdir() + "/samples.parquet"
|
|
25
|
+
sits_to_parquet(samples_modis_ndvi, file=parquet_file)
|
|
26
|
+
samples = sits_from_parquet(parquet_file)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Describe a data cube as a HuggingFace dataset
|
|
2
|
+
|
|
3
|
+
Data cubes shared on HuggingFace are described by files sits reads to
|
|
4
|
+
understand the dataset. They are kept in a "sits" directory of the
|
|
5
|
+
repository, so they are not mixed with the other files of the dataset:
|
|
6
|
+
|
|
7
|
+
- "sits/sits.yml": the collection definition of the dataset;
|
|
8
|
+
|
|
9
|
+
- "sits/cache.rds": the data cube of the dataset. When it is available,
|
|
10
|
+
sits loads it instead of reading each image of the dataset.
|
|
11
|
+
|
|
12
|
+
This function writes these files in `output_dir`, as they must be uploaded
|
|
13
|
+
to the repository (i.e., the "sits" directory and the images, named as
|
|
14
|
+
sits names them, in the root of the repository). Nothing is uploaded by
|
|
15
|
+
this function.
|
|
16
|
+
|
|
17
|
+
The collection definition is written from a data cube: the bands, their
|
|
18
|
+
resolution and, for results produced by sits (e.g., probabilities,
|
|
19
|
+
classified maps), the labels of the classification.
|
|
20
|
+
|
|
21
|
+
Each type of cube is described the way sits reads it:
|
|
22
|
+
|
|
23
|
+
- image raster cubes are described band by band;
|
|
24
|
+
|
|
25
|
+
- embeddings have only base satellite and sensor described;
|
|
26
|
+
|
|
27
|
+
- results produced by sits inform only their resolution and the labels
|
|
28
|
+
of the classification.
|
|
29
|
+
|
|
30
|
+
A dataset can share more than one result of the same classification
|
|
31
|
+
(e.g., probabilities and the classified map), which are described
|
|
32
|
+
together when they are informed as a list of cubes. A cache describes a
|
|
33
|
+
single cube, so it is not written for a list of cubes.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
cube (SITSCubeModel | list[SITSCubeModel]): Data cube or list of cubes
|
|
37
|
+
to be shared as a dataset.
|
|
38
|
+
|
|
39
|
+
output_dir (str | pathlib.Path): Existing directory where the files of
|
|
40
|
+
the dataset are written (optional). When not informed, the
|
|
41
|
+
collection definition is only returned.
|
|
42
|
+
|
|
43
|
+
repo (str): HuggingFace repository where the images are uploaded
|
|
44
|
+
("<user>/<dataset>"). Required to write the cache of a data cube,
|
|
45
|
+
unless the cube was read from HuggingFace.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
SITStructureData: Collection definition of the dataset.
|
|
49
|
+
|
|
50
|
+
Note:
|
|
51
|
+
Images must be named in the dataset as sits names them
|
|
52
|
+
(`sits_cube_copy` and `sits_regularize` do it), and only the bands
|
|
53
|
+
shared in the dataset must be described.
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
import tempfile
|
|
57
|
+
from pysits import *
|
|
58
|
+
|
|
59
|
+
# create a cube
|
|
60
|
+
data_dir = r_package_dir("extdata/raster/mod13q1", package="sits")
|
|
61
|
+
cube = sits_cube(
|
|
62
|
+
source="BDC",
|
|
63
|
+
collection="MOD13Q1-6.1",
|
|
64
|
+
data_dir=data_dir,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# get the collection definition of the cube
|
|
68
|
+
collection_conf = sits_to_hf(cube)
|
|
69
|
+
|
|
70
|
+
# write the files describing the dataset ("sits/sits.yml" and
|
|
71
|
+
# "sits/cache.rds"), to be uploaded with the images of the cube
|
|
72
|
+
sits_to_hf(
|
|
73
|
+
cube,
|
|
74
|
+
output_dir=tempfile.gettempdir(),
|
|
75
|
+
repo="user/dataset",
|
|
76
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Export sits time series to the Parquet format
|
|
2
|
+
|
|
3
|
+
Writes a set of time series to a Parquet file. The layout is long: one
|
|
4
|
+
row per sample and date, with the time series as plain columns. The
|
|
5
|
+
file metadata keeps what is needed to rebuild the data with
|
|
6
|
+
`sits_from_parquet` (class, column order and bands). It also follows
|
|
7
|
+
GeoParquet 1.1, so tools like GDAL and QGIS read the file as points.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
data (SITSTimeSeriesModel): Time series.
|
|
11
|
+
|
|
12
|
+
file (str | pathlib.Path): Full path of the exported file (valid
|
|
13
|
+
file name with extension ".parquet").
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
None
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
import tempfile
|
|
20
|
+
from pysits import *
|
|
21
|
+
|
|
22
|
+
parquet_file = tempfile.gettempdir() + "/samples.parquet"
|
|
23
|
+
sits_to_parquet(samples_modis_ndvi, file=parquet_file)
|
|
@@ -17,7 +17,14 @@
|
|
|
17
17
|
|
|
18
18
|
"""Exporters module."""
|
|
19
19
|
|
|
20
|
-
from .files import
|
|
20
|
+
from .files import (
|
|
21
|
+
sits_from_parquet,
|
|
22
|
+
sits_timeseries_to_csv,
|
|
23
|
+
sits_to_csv,
|
|
24
|
+
sits_to_parquet,
|
|
25
|
+
sits_to_xlsx,
|
|
26
|
+
)
|
|
27
|
+
from .hf import sits_config_to_hf, sits_from_hf, sits_to_hf
|
|
21
28
|
from .sf import sits_as_geopandas
|
|
22
29
|
from .xarray import sits_as_xarray
|
|
23
30
|
|
|
@@ -27,4 +34,9 @@ __all__ = (
|
|
|
27
34
|
"sits_to_csv",
|
|
28
35
|
"sits_to_xlsx",
|
|
29
36
|
"sits_timeseries_to_csv",
|
|
37
|
+
"sits_to_parquet",
|
|
38
|
+
"sits_from_parquet",
|
|
39
|
+
"sits_to_hf",
|
|
40
|
+
"sits_from_hf",
|
|
41
|
+
"sits_config_to_hf",
|
|
30
42
|
)
|
|
@@ -17,10 +17,15 @@
|
|
|
17
17
|
|
|
18
18
|
"""Files exporter."""
|
|
19
19
|
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
20
22
|
from pysits.backend.pkgs import r_pkg_sits
|
|
21
23
|
from pysits.conversions.decorators import function_call
|
|
22
24
|
from pysits.docs import attach_doc
|
|
23
25
|
from pysits.models.data.frame import SITSFrame
|
|
26
|
+
from pysits.models.data.ts import SITSTimeSeriesModel
|
|
27
|
+
from pysits.models.resolver import resolve_and_invoke_content_class
|
|
28
|
+
from pysits.network import fetch_to_tempfile, is_remote
|
|
24
29
|
|
|
25
30
|
|
|
26
31
|
@function_call(r_pkg_sits.sits_to_csv, SITSFrame)
|
|
@@ -41,3 +46,28 @@ def sits_to_xlsx(*args, **kwargs) -> None:
|
|
|
41
46
|
@attach_doc("sits_timeseries_to_csv")
|
|
42
47
|
def sits_timeseries_to_csv(*args, **kwargs) -> None:
|
|
43
48
|
"""Export a full sits timeseries to CSV format."""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@function_call(r_pkg_sits.sits_to_parquet, lambda x: None)
|
|
52
|
+
@attach_doc("sits_to_parquet")
|
|
53
|
+
def sits_to_parquet(*args, **kwargs) -> None:
|
|
54
|
+
"""Export sits time series to the Parquet format."""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@function_call(r_pkg_sits.sits_from_parquet, resolve_and_invoke_content_class)
|
|
58
|
+
def _sits_from_parquet(*args, **kwargs) -> SITSTimeSeriesModel:
|
|
59
|
+
"""Read sits time series from a local Parquet file."""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@attach_doc("sits_from_parquet")
|
|
63
|
+
def sits_from_parquet(file: str | Path) -> SITSTimeSeriesModel:
|
|
64
|
+
"""Read sits time series from the Parquet format."""
|
|
65
|
+
# If file is remote
|
|
66
|
+
if is_remote(file):
|
|
67
|
+
# Download it to a temporary file
|
|
68
|
+
with fetch_to_tempfile(str(file), suffix=".parquet") as local_file:
|
|
69
|
+
# Read it
|
|
70
|
+
return _sits_from_parquet(local_file)
|
|
71
|
+
|
|
72
|
+
# Otherwise, read it directly
|
|
73
|
+
return _sits_from_parquet(file)
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
"""HuggingFace exporter."""
|
|
19
|
+
|
|
20
|
+
from pysits.backend.functions import r_fnc_unname
|
|
21
|
+
from pysits.backend.pkgs import r_pkg_sits
|
|
22
|
+
from pysits.conversions.common import convert_to_r
|
|
23
|
+
from pysits.conversions.decorators import function_call, rpy2_fix_type_custom
|
|
24
|
+
from pysits.docs import attach_doc
|
|
25
|
+
from pysits.models.data.base import SITStructureData
|
|
26
|
+
from pysits.models.data.cube import SITSCubeModel
|
|
27
|
+
from pysits.models.data.ts import SITSTimeSeriesModel
|
|
28
|
+
from pysits.models.ml import SITSMachineLearningMethod
|
|
29
|
+
from pysits.models.resolver import resolve_and_invoke_content_class
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# HuggingFace-specific converters functions
|
|
34
|
+
#
|
|
35
|
+
def convert_hf_cubes(obj: object) -> object:
|
|
36
|
+
"""Convert a list of cubes to an unnamed R list."""
|
|
37
|
+
if isinstance(obj, list | tuple):
|
|
38
|
+
return r_fnc_unname(convert_to_r(obj))
|
|
39
|
+
|
|
40
|
+
return obj
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# HuggingFace-specific converters config
|
|
45
|
+
#
|
|
46
|
+
hf_converters = {
|
|
47
|
+
"cube": convert_hf_cubes,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# HuggingFace
|
|
53
|
+
#
|
|
54
|
+
@function_call(r_pkg_sits.sits_from_hf, resolve_and_invoke_content_class)
|
|
55
|
+
@attach_doc("sits_from_hf")
|
|
56
|
+
def sits_from_hf(
|
|
57
|
+
*args, **kwargs
|
|
58
|
+
) -> SITSCubeModel | SITSTimeSeriesModel | SITSMachineLearningMethod:
|
|
59
|
+
"""Read data cubes, samples and models shared on HuggingFace."""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@rpy2_fix_type_custom(converters=hf_converters)
|
|
63
|
+
@function_call(r_pkg_sits.sits_to_hf, SITStructureData)
|
|
64
|
+
@attach_doc("sits_to_hf")
|
|
65
|
+
def sits_to_hf(
|
|
66
|
+
cube: SITSCubeModel | list[SITSCubeModel], *args, **kwargs
|
|
67
|
+
) -> SITStructureData:
|
|
68
|
+
"""Describe a data cube as a HuggingFace dataset."""
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@function_call(r_pkg_sits.sits_config_to_hf, SITStructureData)
|
|
72
|
+
@attach_doc("sits_config_to_hf")
|
|
73
|
+
def sits_config_to_hf(*args, **kwargs) -> SITStructureData:
|
|
74
|
+
"""Describe a collection of sits as a HuggingFace dataset."""
|
|
@@ -25,8 +25,15 @@ import pytest
|
|
|
25
25
|
from pysits.backend.pkgs import r_pkg_sits
|
|
26
26
|
from pysits.models.data.frame import SITSFrame
|
|
27
27
|
from pysits.models.data.matrix import SITSConfusionMatrix
|
|
28
|
+
from pysits.models.data.ts import SITSTimeSeriesModel
|
|
28
29
|
from pysits.sits.context import cerrado_2classes
|
|
29
|
-
from pysits.sits.exporters import
|
|
30
|
+
from pysits.sits.exporters import (
|
|
31
|
+
sits_from_parquet,
|
|
32
|
+
sits_timeseries_to_csv,
|
|
33
|
+
sits_to_csv,
|
|
34
|
+
sits_to_parquet,
|
|
35
|
+
sits_to_xlsx,
|
|
36
|
+
)
|
|
30
37
|
from pysits.sits.ml import sits_rfor
|
|
31
38
|
from pysits.sits.ts import sits_sample, sits_validate
|
|
32
39
|
|
|
@@ -94,3 +101,46 @@ def test_sits_to_xlsx(tmp_path: Path, accuracy):
|
|
|
94
101
|
r_pkg_sits.sits_to_xlsx(accuracy._instance, file=str(r_file))
|
|
95
102
|
|
|
96
103
|
assert read_xlsx(py_file) == read_xlsx(r_file)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_sits_parquet(tmp_path: Path):
|
|
107
|
+
"""Test time series export / import using parquet."""
|
|
108
|
+
# local file
|
|
109
|
+
file = tmp_path / "samples.parquet"
|
|
110
|
+
|
|
111
|
+
# export samples as parquet
|
|
112
|
+
sits_to_parquet(cerrado_2classes, file=file)
|
|
113
|
+
|
|
114
|
+
# import samples from parquet
|
|
115
|
+
samples = sits_from_parquet(file)
|
|
116
|
+
|
|
117
|
+
# samples must be a time series model
|
|
118
|
+
assert isinstance(samples, SITSTimeSeriesModel)
|
|
119
|
+
|
|
120
|
+
# metadata and nested series must be equal to the original samples
|
|
121
|
+
metadata = samples.drop(columns="time_series")
|
|
122
|
+
expected = cerrado_2classes.drop(columns="time_series")
|
|
123
|
+
|
|
124
|
+
assert metadata.equals(expected)
|
|
125
|
+
assert all(
|
|
126
|
+
ts.equals(expected_ts)
|
|
127
|
+
for ts, expected_ts in zip(
|
|
128
|
+
samples["time_series"], cerrado_2classes["time_series"], strict=True
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_sits_from_parquet_remote(http_server):
|
|
134
|
+
"""Test time series import using remote parquet file."""
|
|
135
|
+
# remote file
|
|
136
|
+
directory, base_url = http_server
|
|
137
|
+
|
|
138
|
+
# export samples as parquet
|
|
139
|
+
sits_to_parquet(cerrado_2classes, file=directory / "samples.parquet")
|
|
140
|
+
|
|
141
|
+
# import samples from parquet
|
|
142
|
+
samples = sits_from_parquet(f"{base_url}/samples.parquet")
|
|
143
|
+
|
|
144
|
+
# samples must be a time series model
|
|
145
|
+
assert isinstance(samples, SITSTimeSeriesModel)
|
|
146
|
+
assert len(samples) == len(cerrado_2classes)
|
|
@@ -0,0 +1,154 @@
|
|
|
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
|
+
"""Unit tests for HuggingFace export operations."""
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
import httpx2
|
|
23
|
+
import pytest
|
|
24
|
+
|
|
25
|
+
from pysits.backend.pkgs import r_pkg_sits
|
|
26
|
+
from pysits.models.data.base import SITStructureData
|
|
27
|
+
from pysits.models.data.cube import SITSCubeModel
|
|
28
|
+
from pysits.models.data.ts import SITSTimeSeriesModel
|
|
29
|
+
from pysits.models.ml import SITSMachineLearningMethod
|
|
30
|
+
from pysits.sits.exporters import sits_config_to_hf, sits_from_hf, sits_to_hf
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# Helpers
|
|
35
|
+
#
|
|
36
|
+
def list_files(directory: Path) -> list[str]:
|
|
37
|
+
"""List the files of a directory."""
|
|
38
|
+
return sorted(
|
|
39
|
+
file.relative_to(directory).as_posix()
|
|
40
|
+
for file in directory.rglob("*")
|
|
41
|
+
if file.is_file()
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Fixtures
|
|
47
|
+
#
|
|
48
|
+
@pytest.fixture(scope="module")
|
|
49
|
+
def hf_online() -> None:
|
|
50
|
+
"""Skip the tests of a module when HuggingFace is not accessible."""
|
|
51
|
+
try:
|
|
52
|
+
httpx2.head("https://huggingface.co", follow_redirects=True)
|
|
53
|
+
|
|
54
|
+
except httpx2.HTTPError:
|
|
55
|
+
pytest.skip("HuggingFace is not accessible")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Tests
|
|
60
|
+
#
|
|
61
|
+
def test_sits_to_hf(local_cube, tmp_path: Path):
|
|
62
|
+
"""Test data cube described as a HuggingFace dataset."""
|
|
63
|
+
py_dir = tmp_path / "python"
|
|
64
|
+
r_dir = tmp_path / "r"
|
|
65
|
+
list_dir = tmp_path / "list"
|
|
66
|
+
|
|
67
|
+
for directory in (py_dir, r_dir, list_dir):
|
|
68
|
+
directory.mkdir()
|
|
69
|
+
|
|
70
|
+
# single cube, definition and cache are written
|
|
71
|
+
result = sits_to_hf(local_cube, output_dir=py_dir, repo="user/dataset")
|
|
72
|
+
r_pkg_sits.sits_to_hf(
|
|
73
|
+
local_cube._instance, output_dir=str(r_dir), repo="user/dataset"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# validate the results
|
|
77
|
+
assert isinstance(result, SITStructureData)
|
|
78
|
+
assert list_files(py_dir) == ["sits/cache.rds", "sits/sits.yml"]
|
|
79
|
+
|
|
80
|
+
# read the results
|
|
81
|
+
result_py = (py_dir / "sits/sits.yml").read_text()
|
|
82
|
+
result_r = (r_dir / "sits/sits.yml").read_text()
|
|
83
|
+
|
|
84
|
+
assert result_py == result_r
|
|
85
|
+
|
|
86
|
+
# convert list of cubes
|
|
87
|
+
sits_to_hf([local_cube], output_dir=list_dir)
|
|
88
|
+
|
|
89
|
+
# test - only the definition is written, cache is not supported
|
|
90
|
+
assert list_files(list_dir) == ["sits/sits.yml"]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_sits_config_to_hf(tmp_path: Path):
|
|
94
|
+
"""Test collection described as a HuggingFace dataset."""
|
|
95
|
+
py_dir = tmp_path / "python"
|
|
96
|
+
r_dir = tmp_path / "r"
|
|
97
|
+
|
|
98
|
+
for directory in (py_dir, r_dir):
|
|
99
|
+
directory.mkdir()
|
|
100
|
+
|
|
101
|
+
# convert collection
|
|
102
|
+
result = sits_config_to_hf(
|
|
103
|
+
source="MPC",
|
|
104
|
+
collection="SENTINEL-2-L2A",
|
|
105
|
+
bands=["B02", "B03"],
|
|
106
|
+
output_dir=py_dir,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# convert collection in R
|
|
110
|
+
r_pkg_sits.sits_config_to_hf(
|
|
111
|
+
source="MPC",
|
|
112
|
+
collection="SENTINEL-2-L2A",
|
|
113
|
+
bands=["B02", "B03"],
|
|
114
|
+
output_dir=str(r_dir),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# validate the results
|
|
118
|
+
assert isinstance(result, SITStructureData)
|
|
119
|
+
assert list_files(py_dir) == ["sits/sits.yml"]
|
|
120
|
+
|
|
121
|
+
# read the results
|
|
122
|
+
result_py = (py_dir / "sits/sits.yml").read_text()
|
|
123
|
+
result_r = (r_dir / "sits/sits.yml").read_text()
|
|
124
|
+
|
|
125
|
+
assert result_py == result_r
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@pytest.mark.parametrize(
|
|
129
|
+
"repo, options, expected",
|
|
130
|
+
[
|
|
131
|
+
(
|
|
132
|
+
"felipemcarlos/sits_mod13q1_sinop",
|
|
133
|
+
{"start_date": "2013-09-14", "end_date": "2013-10-16"},
|
|
134
|
+
SITSCubeModel,
|
|
135
|
+
),
|
|
136
|
+
("felipemcarlos/sits_samples_modis_ndvi", {}, SITSTimeSeriesModel),
|
|
137
|
+
(
|
|
138
|
+
"felipemcarlos/sits_rfor_modis_ndvi",
|
|
139
|
+
{"type": "model"},
|
|
140
|
+
SITSMachineLearningMethod,
|
|
141
|
+
),
|
|
142
|
+
],
|
|
143
|
+
)
|
|
144
|
+
def test_sits_from_hf(hf_online, tmp_path: Path, repo: str, options: dict, expected):
|
|
145
|
+
"""Test data cube, samples and model read from HuggingFace."""
|
|
146
|
+
result = sits_from_hf(
|
|
147
|
+
repo,
|
|
148
|
+
output_dir=tmp_path,
|
|
149
|
+
progress=False,
|
|
150
|
+
**options,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# validate the results
|
|
154
|
+
assert isinstance(result, expected)
|