From 70200aca39c2d61fbe308a103f3487501062cd23 Mon Sep 17 00:00:00 2001 From: Jake Lee Date: Tue, 8 Jul 2025 18:22:22 -0700 Subject: [PATCH 1/5] ENVI hdr to img --- spectf/dataset.py | 34 ++++++++++++++++++------------- spectf/toa.py | 4 ++-- spectf/utils.py | 24 ++++++++++++++++++++++ spectf_cloud/deploy/deploy_pt.py | 7 ++++++- spectf_cloud/deploy/deploy_trt.py | 7 ++++++- 5 files changed, 58 insertions(+), 18 deletions(-) diff --git a/spectf/dataset.py b/spectf/dataset.py index 16266dd..e1d27b1 100644 --- a/spectf/dataset.py +++ b/spectf/dataset.py @@ -6,6 +6,7 @@ Author: Jake Lee, jake.h.lee@jpl.nasa.gov """ +import os from collections.abc import Callable from typing import List @@ -14,7 +15,7 @@ from torch.utils.data import Dataset from spectf.toa import l1b_to_toa_arr -from spectf.utils import drop_bands +from spectf.utils import drop_bands, envi_header class RasterDatasetTOA(Dataset): @@ -22,29 +23,26 @@ class RasterDatasetTOA(Dataset): reflectance data derived from L1b rdn. Attributes: - shape (tuple): The shape of the L1b rdn raster. - toa_arr (ndarray): The top-of-atmosphere reflectance data, - reshaped as a list of pixels. - banddef (np.array): The band wavelengths corresponding to the - `toa_arr` indices. + shape (tuple): Shape of the L1b rdn raster. + toa_arr (ndarray): TOA reflectance data reshaped as a list of pixels. + banddef (np.array): Band wavelengths corresponding to `toa_arr` indices. metadata (dict): Metadata of the original raster image. - transform (callable, optional): Transformations or normalizations - for each pixel spectra. + transform (callable, optional): Transformations for each pixel spectra. - The class relies on the `l1b_to_toa_arr` function to process the input data - files and generate the TOA reflectance data. + Relies on the `l1b_to_toa_arr` function to process input data files and generate + TOA reflectance data. """ def __init__( self, rdnfp: str, obsfp: str, - irrfp:str, - rm_bands:List[List[int]]=None, + irrfp: str, + rm_bands: List[List[int]]=None, transform: Callable = None, keep_bands: bool = False, dtype: torch.dtype = torch.float, - device:torch.device = None, + device: torch.device = None, ): """ Initialize the RasterDatasetTOA Dataset object. Args: @@ -57,7 +55,15 @@ def __init__( """ super().__init__() - self.toa_arr, self.banddef, self.metadata = l1b_to_toa_arr(rdnfp, obsfp, irrfp) + # Raster files + self.rdnhdr = envi_header(rdnfp) + self.obshdr = envi_header(obsfp) + + assert os.path.exists(self.rdnhdr), f"Header file {self.rdnhdr} does not exist." + assert os.path.exists(self.obshdr), f"Header file {self.obshdr} does not exist." + assert os.path.exists(irrfp), f"Irradiance file {irrfp} does not exist." + + self.toa_arr, self.banddef, self.metadata = l1b_to_toa_arr(self.rdnhdr, self.obshdr, irrfp) self.shape = self.toa_arr.shape self.toa_arr = self.toa_arr.reshape((self.shape[0] * self.shape[1], self.shape[2])) diff --git a/spectf/toa.py b/spectf/toa.py index 3fc4b97..96fffd9 100644 --- a/spectf/toa.py +++ b/spectf/toa.py @@ -20,8 +20,8 @@ def l1b_to_toa_arr(rdnfp: str, obsfp: str, irrfp: str): Converts Level 1b radiance data to top-of-atmosphere (TOA) reflectance. Args: - rdnfp (str): File path to the radiance data (L1b product). - obsfp (str): File path to the observation data (L1b product). + rdnfp (str): File path to the radiance data (L1b product .hdr). + obsfp (str): File path to the observation data (L1b product .hdr). irrfp (str): File path to the irradiance data (.npy). Returns: diff --git a/spectf/utils.py b/spectf/utils.py index b6f50cf..aa27619 100644 --- a/spectf/utils.py +++ b/spectf/utils.py @@ -42,6 +42,30 @@ def get_date(fid:str) -> str: """ Get the date string from full FID """ return fid.split('_')[0].split('t')[1] +def envi_header(inputpath): + """ + https://github.com/emit-sds/emit-utils/blob/develop/emit_utils/file_checks.py + Convert a envi binary/header path to a header, handling extensions + Args: + inputpath: path to envi binary file + Returns: + str: the header file associated with the input reference. + + """ + if op.splitext(inputpath)[-1] == '.img' or op.splitext(inputpath)[-1] == '.dat' or op.splitext(inputpath)[-1] == '.raw': + # headers could be at either filename.img.hdr or filename.hdr. Check both, return the one that exists if it + # does, if not return the latter (new file creation presumed). + hdrfile = op.splitext(inputpath)[0] + '.hdr' + if op.isfile(hdrfile): + return hdrfile + elif op.isfile(inputpath + '.hdr'): + return inputpath + '.hdr' + return hdrfile + elif op.splitext(inputpath)[-1] == '.hdr': + return inputpath + else: + return inputpath + '.hdr' + def drop_bands( spectra: np.ndarray, banddef: np.ndarray, diff --git a/spectf_cloud/deploy/deploy_pt.py b/spectf_cloud/deploy/deploy_pt.py index daedffa..1f54631 100644 --- a/spectf_cloud/deploy/deploy_pt.py +++ b/spectf_cloud/deploy/deploy_pt.py @@ -124,7 +124,12 @@ ) @spectf_cloud.command( add_help_option=True, - help="Produce a SpecTf transformer-generated cloud mask using PyTorch runtime." + help="""Produce a SpecTf transformer-generated cloud mask using PyTorch runtime. + + OUTFP is where the output file will be written (GeoTIFF .tif) + RDNFP is the filepath of the radiance data (ENVI .img) + OBSFP is the filepath of the observation data (ENVI .img) + """ ) def deploy_pt( rdnfp, diff --git a/spectf_cloud/deploy/deploy_trt.py b/spectf_cloud/deploy/deploy_trt.py index 241275c..3b81fd3 100644 --- a/spectf_cloud/deploy/deploy_trt.py +++ b/spectf_cloud/deploy/deploy_trt.py @@ -120,7 +120,12 @@ ) @spectf_cloud.command( add_help_option=True, - help="Produce a SpecTf transformer-generated cloud mask using the TensorRT engine." + help="""Produce a SpecTf transformer-generated cloud mask using the TensorRT engine. + + OUTFP is where the output file will be written (GeoTIFF .tif) + RDNFP is the filepath of the radiance data (ENVI .img) + OBSFP is the filepath of the observation data (ENVI .img) + """ ) def deploy_trt( rdnfp, From ba8deeeaf29eae2d9bd87bde783334d512230d9c Mon Sep 17 00:00:00 2001 From: Jake Lee Date: Tue, 8 Jul 2025 18:32:15 -0700 Subject: [PATCH 2/5] Documentation update --- spectf_cloud/README.md | 83 +++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/spectf_cloud/README.md b/spectf_cloud/README.md index c72d3b7..927dbb3 100644 --- a/spectf_cloud/README.md +++ b/spectf_cloud/README.md @@ -1,8 +1,8 @@ # SpecTf: Transformers Enable Data-Driven Imaging Spectroscopy Cloud Detection -Jake H. Lee, Michael Kiper, David R. Thompson, Philip G. Brodrick. *In Review.* - -Preprint: https://arxiv.org/abs/2501.04916 +Jake H. Lee, Michael Kiper, David R. Thompson, Philip G. Brodrick +Proceedings of the National Academy of Sciences of the United States of America +122 (27) e2502903122, https://doi.org/10.1073/pnas.2502903122 (2025). @@ -86,21 +86,25 @@ Within each of these datasets, there the following fields: At any point, you can navigate the CLI with the `-h` `--help` flags ``` $ spectf-cloud -h + + Usage: spectf-cloud [OPTIONS] COMMAND [ARGS]... + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +│ --version Display the current SpecTf version. │ +│ --help -h Show this message and exit. │ +╰──────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────╮ +│ cloud-eval Evaluation commands for SpecTf and L2A Baseline. │ +│ deploy-pt Produce a SpecTf transformer-generated cloud mask using │ +│ PyTorch runtime. │ +│ deploy-trt Produce a SpecTf transformer-generated cloud mask using │ +│ the TensorRT engine. │ +│ train Train the SpecTf Hyperspectral Transformer Model. │ +│ train-comparison Training commands for the ResNet and XGBoost comparison │ +│ models. │ +│ tui Open Textual TUI. │ +╰──────────────────────────────────────────────────────────────────────────────╯ - Usage: spectf-cloud [OPTIONS] COMMAND [ARGS]... - -╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────╮ -│ --version Display the current SpecTf version. │ -│ --help -h Show this message and exit. │ -╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ -╭─ Commands ────────────────────────────────────────────────────────────────────────────────────────────╮ -│ cloud-eval Evaluation commands for SpecTf and L2A Baseline. │ -│ deploy-pt Produce a SpecTf transformer-generated cloud mask using PyTorch runtime. │ -│ deploy-trt Produce a SpecTf transformer-generated cloud mask using the TensorRT engine. │ -│ train Train the SpecTf Hyperspectral Transformer Model. │ -│ train-comparison Training commands for the ResNet and XGBoost comparison models. │ -│ tui Open Textual TUI. │ -╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ``` ### 🌈 Using `SpecTf Cloud` to cloud mask your EMIT Scene ☁️ @@ -121,23 +125,34 @@ $ which spectf-cloud ``` $ spectf-cloud deploy-pt -h - - Usage: spectf-cloud deploy-pt [OPTIONS] OUTFP OBSFP RDNFP - - Produce a SpecTf transformer-generated cloud mask. - -╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ --threshold FLOAT Threshold for cloud classification. [default: 0.52] │ -│ --device INTEGER Device specification for PyTorch (-1 for CPU, 0+ for GPU, MPS if │ -│ available). │ -│ [default: -1] │ -│ --arch-spec FILE Filepath to model architecture YAML specification. [default: spectf_cloud_config.yml] │ -│ --irradiance FILE Filepath to irradiance numpy file. [default: irr.npy] │ -│ --weights FILE Filepath to trained model weights. [default: weights/current.pt] │ -│ --proba Output probability map instead of binary cloud mask. │ -│ --keep-bands Keep all bands in the spectra (use for non-EMIT data). │ -│ --help -h Show this message and exit. │ -╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + Usage: spectf-cloud deploy-pt [OPTIONS] OUTFP OBSFP RDNFP + + Produce a SpecTf transformer-generated cloud mask using PyTorch runtime. + OUTFP is where the output file will be written (GeoTIFF .tif) RDNFP is the + filepath of the radiance data (ENVI .img) OBSFP is the filepath of the + observation data (ENVI .img) + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +│ --threshold FLOAT Threshold for cloud classification. │ +│ [default: 0.51] │ +│ --device INTEGER Device specification for PyTorch (-1 for CPU, 0+ │ +│ for GPU, MPS if available). │ +│ [default: -1] │ +│ --arch-spec FILE Filepath to model architecture YAML │ +│ specification. This file also needs to contain │ +│ the bands to remove │ +│ [default: SpecTf/spectf_cloud/spectf_cloud_confi… | +│ --irradiance FILE Filepath to irradiance numpy file. │ +│ [default: SpecTf/spectf_cloud/irr.npy] │ +│ --weights FILE Filepath to latest trained model weights. │ +│ [default: SpecTf/spectf_cloud/weights/current.pt │ +│ --proba Output probability map instead of binary cloud │ +│ mask. │ +│ --keep-bands Keep all bands in the spectra (use for non-EMIT │ +│ data). │ +│ --help -h Show this message and exit. │ +╰──────────────────────────────────────────────────────────────────────────────╯ ``` Example: From dba376f53f503a96a7af5a064344b79717fcec86 Mon Sep 17 00:00:00 2001 From: Jake Lee Date: Tue, 8 Jul 2025 18:51:58 -0700 Subject: [PATCH 3/5] Update default threshold --- spectf_cloud/evaluation/eval_spectf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spectf_cloud/evaluation/eval_spectf.py b/spectf_cloud/evaluation/eval_spectf.py index d6644d9..90ac34f 100644 --- a/spectf_cloud/evaluation/eval_spectf.py +++ b/spectf_cloud/evaluation/eval_spectf.py @@ -83,7 +83,7 @@ ) @click.option( "--thresh", - default=0.52, + default=0.51, type=float, show_default=True, help="Cloud classification posterior score threshold.", From cd031ad50e7b53f21c81f633768749e8b17b6d9f Mon Sep 17 00:00:00 2001 From: Jake Lee Date: Tue, 8 Jul 2025 19:13:45 -0700 Subject: [PATCH 4/5] Perf metrics, closes #83 --- spectf_cloud/weights/README.md | 18 ++++++++++++++++++ spectf_cloud/weights/v0.0.1/README.md | 15 +++++++-------- spectf_cloud/weights/v0.1.0/README.md | 20 +++++++++----------- 3 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 spectf_cloud/weights/README.md diff --git a/spectf_cloud/weights/README.md b/spectf_cloud/weights/README.md new file mode 100644 index 0000000..34a541d --- /dev/null +++ b/spectf_cloud/weights/README.md @@ -0,0 +1,18 @@ +# Model Weights + +This directory contains versions of the SpecTf EMIT Cloud model. + +- `v0.0.1` + - Published model version +- `v0.1.0` + - Updated model trained on a larger dataset, in preparation for EMIT cloud + mask product delivery + +## Performance Metrics + +_F1-Scores on each test set. *Reported in publication._ + +| Model | Threshold | Labelbox | MMGIS | MMGIS-2 | L+M | L+M+M2 | +| ------ | --------- | -------- | ----- | ------- | ------ | ------ | +| v0.0.1 | 0.52 | 0.919 | 0.988 | 0.860 | 0.952* | 0.915 | +| v0.1.0 | 0.51 | 0.912 | 0.996 | 0.943 | 0.952 | 0.948 | \ No newline at end of file diff --git a/spectf_cloud/weights/v0.0.1/README.md b/spectf_cloud/weights/v0.0.1/README.md index 103ddd0..c96ba10 100644 --- a/spectf_cloud/weights/v0.0.1/README.md +++ b/spectf_cloud/weights/v0.0.1/README.md @@ -1,3 +1,5 @@ +# v0.0.1 + ## Files: - weights.pt - md5sum: c54fe5ef078b44182d3cc626008959ab @@ -6,13 +8,10 @@ - model.engine - md5sum: 439cf0d5aa33d64b2340c74527f16aef -## Datasets: +## Training Datasets: +_The following links direct to Zenodo downloads._ + - [labelbox](https://zenodo.org/records/15833303/files/spectf_cloud_lbox.hdf5?download=1) - - samples: + - 4.1 GB, 1,841,641 spectra - [mmgis](https://zenodo.org/records/15833303/files/spectf_cloud_mmgis.hdf5?download=1) - - samples: - -## Test Best-F1 Scores: -| Model | **Lbox + MMGISv1** | Thresh | -| ------ | ------------------ | ------ | -| v0.0.1 | 0.9519 | 0.52 | \ No newline at end of file + - 3.9 GB, 1,733,801 spectra \ No newline at end of file diff --git a/spectf_cloud/weights/v0.1.0/README.md b/spectf_cloud/weights/v0.1.0/README.md index d06110a..758e77a 100644 --- a/spectf_cloud/weights/v0.1.0/README.md +++ b/spectf_cloud/weights/v0.1.0/README.md @@ -1,3 +1,5 @@ +# v0.1.0 + ## Files: - weights.pt - md5sum: 85d969fb86708175fcd2aaf488a19162 @@ -6,16 +8,12 @@ - model.engine - md5sum: 99ac6abb33dff3b08f241cd7cdeab828 -## Datasets: +## Training Datasets: +_The following links direct to Zenodo downloads._ + - [labelbox](https://zenodo.org/records/15833303/files/spectf_cloud_lbox.hdf5?download=1) - - samples: + - 4.1 GB, 1,841,641 spectra - [mmgis](https://zenodo.org/records/15833303/files/spectf_cloud_mmgis.hdf5?download=1) - - samples: -- [mmgis-v2](https://zenodo.org/records/15833303/files/spectf_cloud_mmgis_2.hdf5?download=1) - - samples: - -## Test Best-F1 Scores: -| Model | **Lbox + MMGISv1 + MMGISv2** | Thresh | **Lbox + MMGISv1** | Thresh | **MMGISv2** | Thresh | -| ----------------- | ---------------------------- | ------ | ------------------ | ------ | ----------- | ------ | -| v0.0.1 | 0.9152 | 0.55 | 0.9519 | 0.52 | 0.8604 | 0.53 | -| v0.1.0 (this one) | 0.9484 | 0.51 | 0.9524 | 0.52 | 0.9428 | 0.51 | + - 3.9 GB, 1,733,801 spectra +- [mmgis-2](https://zenodo.org/records/15833303/files/spectf_cloud_mmgis_2.hdf5?download=1) + - 8.0 GB, 3,606,820 spectra \ No newline at end of file From 604dc5679bd2f4ec719c107e7823b04b8e336fcc Mon Sep 17 00:00:00 2001 From: Jake Lee Date: Tue, 8 Jul 2025 19:13:59 -0700 Subject: [PATCH 5/5] Updated train/test csvs --- spectf_cloud/datasets/test_fids.csv | 57 ++++ spectf_cloud/datasets/train_fids.csv | 383 +++++++++++++++++++++++++++ 2 files changed, 440 insertions(+) diff --git a/spectf_cloud/datasets/test_fids.csv b/spectf_cloud/datasets/test_fids.csv index 2e53e6f..c85bee6 100644 --- a/spectf_cloud/datasets/test_fids.csv +++ b/spectf_cloud/datasets/test_fids.csv @@ -28,10 +28,20 @@ emit20230524t080731 emit20230526t141654 emit20230605t045030 emit20231006t052426 +emit20240101t021631 +emit20240101t101617 +emit20240201t051020 +emit20240201t065205 +emit20240201t112745 +emit20240201t130346 +emit20240201t191530 emit20240301t031712 emit20240301t032602 +emit20240301t060903 emit20240301t060915 emit20240301t061049 +emit20240301t061137 +emit20240301t140747 emit20240301t153909 emit20240301t154317 emit20240301t154352 @@ -67,3 +77,50 @@ emit20240306t070724 emit20240306t131716 emit20240306t131950 emit20240307t123027 +emit20240401t073643 +emit20240401t074238 +emit20240401t091746 +emit20240401t105337 +emit20240401t165720 +emit20240401t201009 +emit20240401t201219 +emit20240501t060729 +emit20240501t092015 +emit20240501t153409 +emit20240601t002507 +emit20240601t002519 +emit20240601t063805 +emit20240601t070705 +emit20240601t083926 +emit20240601t114551 +emit20240601t145029 +emit20240601t210302 +emit20240601t233834 +emit20240601t233857 +emit20240701t083148 +emit20240701t083311 +emit20240701t130602 +emit20240701t144917 +emit20240801t050523 +emit20240801t050907 +emit20240801t064156 +emit20240801t064623 +emit20240801t094804 +emit20240801t111918 +emit20240801t111941 +emit20240801t130136 +emit20240801t155159 +emit20240801t173114 +emit20240801t173511 +emit20240801t173657 +emit20240801t190552 +emit20240801t190604 +emit20240801t190913 +emit20240801t204038 +emit20240801t204347 +emit20240801t221914 +emit20240901t013613 +emit20240901t073802 +emit20240901t121449 +emit20240901t153014 +emit20241101t092401 diff --git a/spectf_cloud/datasets/train_fids.csv b/spectf_cloud/datasets/train_fids.csv index 125bd37..2e4bba1 100644 --- a/spectf_cloud/datasets/train_fids.csv +++ b/spectf_cloud/datasets/train_fids.csv @@ -189,8 +189,58 @@ emit20231019t075222 emit20231019t075234 emit20231023t061716 emit20231029t030909 +emit20240101t010326 +emit20240101t021643 +emit20240101t021655 +emit20240101t021707 +emit20240101t021719 +emit20240101t021731 +emit20240101t021742 +emit20240101t021754 +emit20240101t101605 +emit20240101t144459 +emit20240101t162847 +emit20240101t162859 +emit20240101t162910 +emit20240101t162922 +emit20240101t163107 +emit20240101t163119 +emit20240201t034438 +emit20240201t034449 +emit20240201t034501 +emit20240201t050944 +emit20240201t051323 +emit20240201t051335 +emit20240201t051347 +emit20240201t051359 +emit20240201t064826 +emit20240201t064838 +emit20240201t064902 +emit20240201t064914 +emit20240201t064925 +emit20240201t081329 +emit20240201t081341 +emit20240201t081353 +emit20240201t081516 +emit20240201t081528 +emit20240201t082310 +emit20240201t082322 +emit20240201t095245 +emit20240201t095743 +emit20240201t112756 +emit20240201t112808 +emit20240201t113038 +emit20240201t113050 +emit20240201t142458 +emit20240201t191430 +emit20240201t191442 +emit20240201t191454 +emit20240201t191542 +emit20240201t215816 +emit20240201t215827 emit20240301t030247 emit20240301t030259 +emit20240301t030311 emit20240301t031232 emit20240301t031244 emit20240301t031256 @@ -204,20 +254,32 @@ emit20240301t031847 emit20240301t031858 emit20240301t032109 emit20240301t032132 +emit20240301t060851 emit20240301t060903 +emit20240301t060915 emit20240301t060927 emit20240301t060950 emit20240301t061014 emit20240301t061026 emit20240301t061038 +emit20240301t061049 +emit20240301t061101 +emit20240301t061113 +emit20240301t061200 emit20240301t074237 +emit20240301t074249 emit20240301t074914 emit20240301t075649 emit20240301t093107 +emit20240301t093119 +emit20240301t093130 +emit20240301t093142 +emit20240301t093154 emit20240301t140624 emit20240301t140700 emit20240301t140711 emit20240301t140723 +emit20240301t140759 emit20240301t153536 emit20240301t153548 emit20240301t153559 @@ -236,15 +298,20 @@ emit20240301t154229 emit20240301t154241 emit20240301t154253 emit20240301t154305 +emit20240301t154317 emit20240301t154328 emit20240301t154340 +emit20240301t154352 emit20240301t154503 emit20240301t154515 +emit20240301t154550 emit20240301t171947 emit20240301t171959 emit20240301t172035 +emit20240301t172047 emit20240301t172058 emit20240301t185737 +emit20240301t185749 emit20240301t185836 emit20240301t231304 emit20240302t005432 @@ -463,3 +530,319 @@ emit20240307t123202 emit20240307t123213 emit20240307t123412 emit20240307t123424 +emit20240401t030839 +emit20240401t030851 +emit20240401t073619 +emit20240401t073718 +emit20240401t074004 +emit20240401t074314 +emit20240401t074939 +emit20240401t091218 +emit20240401t091611 +emit20240401t091635 +emit20240401t091646 +emit20240401t091915 +emit20240401t092034 +emit20240401t092058 +emit20240401t092218 +emit20240401t092333 +emit20240401t105009 +emit20240401t105045 +emit20240401t105619 +emit20240401t122621 +emit20240401t122824 +emit20240401t122836 +emit20240401t122848 +emit20240401t165633 +emit20240401t183319 +emit20240401t183331 +emit20240401t183426 +emit20240401t183438 +emit20240401t183450 +emit20240401t183502 +emit20240401t183613 +emit20240401t184057 +emit20240401t200957 +emit20240401t201020 +emit20240401t201032 +emit20240401t201044 +emit20240401t201056 +emit20240401t201108 +emit20240401t201120 +emit20240401t201131 +emit20240401t201143 +emit20240401t201155 +emit20240401t201207 +emit20240401t201231 +emit20240401t201254 +emit20240401t201306 +emit20240401t201318 +emit20240401t201330 +emit20240401t201342 +emit20240501t030548 +emit20240501t073902 +emit20240501t073914 +emit20240501t073926 +emit20240501t074346 +emit20240501t074556 +emit20240501t074632 +emit20240501t074644 +emit20240501t091916 +emit20240501t091928 +emit20240501t092003 +emit20240501t092258 +emit20240501t092536 +emit20240501t135124 +emit20240501t135136 +emit20240501t152148 +emit20240501t152944 +emit20240501t153218 +emit20240501t153346 +emit20240501t153358 +emit20240501t153421 +emit20240501t153433 +emit20240501t153445 +emit20240501t153457 +emit20240501t153509 +emit20240501t153520 +emit20240601t002542 +emit20240601t005531 +emit20240601t020101 +emit20240601t063642 +emit20240601t063654 +emit20240601t063705 +emit20240601t063729 +emit20240601t063741 +emit20240601t063753 +emit20240601t063828 +emit20240601t063840 +emit20240601t063852 +emit20240601t063904 +emit20240601t063916 +emit20240601t070338 +emit20240601t070629 +emit20240601t070641 +emit20240601t070653 +emit20240601t070728 +emit20240601t081129 +emit20240601t081140 +emit20240601t081152 +emit20240601t081204 +emit20240601t081216 +emit20240601t083619 +emit20240601t083914 +emit20240601t083938 +emit20240601t084001 +emit20240601t084013 +emit20240601t084025 +emit20240601t101204 +emit20240601t101216 +emit20240601t101228 +emit20240601t101240 +emit20240601t101252 +emit20240601t101303 +emit20240601t114540 +emit20240601t114603 +emit20240601t124946 +emit20240601t125010 +emit20240601t125022 +emit20240601t125034 +emit20240601t131739 +emit20240601t131751 +emit20240601t145041 +emit20240601t145053 +emit20240601t145105 +emit20240601t145117 +emit20240601t145129 +emit20240601t145140 +emit20240601t162331 +emit20240601t162407 +emit20240601t210250 +emit20240601t210314 +emit20240601t220602 +emit20240601t220637 +emit20240601t223441 +emit20240601t223505 +emit20240601t223540 +emit20240601t223552 +emit20240601t223604 +emit20240601t233845 +emit20240601t233909 +emit20240601t233921 +emit20240601t233957 +emit20240701t021313 +emit20240701t021435 +emit20240701t022307 +emit20240701t082815 +emit20240701t083124 +emit20240701t083136 +emit20240701t083224 +emit20240701t083235 +emit20240701t083259 +emit20240701t083422 +emit20240701t083446 +emit20240701t100042 +emit20240701t100054 +emit20240701t100105 +emit20240701t130538 +emit20240701t130550 +emit20240701t130613 +emit20240701t130836 +emit20240701t130935 +emit20240701t143749 +emit20240701t144007 +emit20240701t144206 +emit20240701t144428 +emit20240701t144451 +emit20240701t144929 +emit20240701t145112 +emit20240701t145124 +emit20240701t162551 +emit20240701t162603 +emit20240701t162615 +emit20240801t033331 +emit20240801t045954 +emit20240801t050323 +emit20240801t050459 +emit20240801t050511 +emit20240801t050535 +emit20240801t050547 +emit20240801t050558 +emit20240801t050610 +emit20240801t050622 +emit20240801t050634 +emit20240801t050646 +emit20240801t050658 +emit20240801t050831 +emit20240801t050918 +emit20240801t063309 +emit20240801t063321 +emit20240801t064120 +emit20240801t064132 +emit20240801t064144 +emit20240801t064207 +emit20240801t064231 +emit20240801t064324 +emit20240801t064400 +emit20240801t064423 +emit20240801t064559 +emit20240801t080946 +emit20240801t081231 +emit20240801t081243 +emit20240801t081254 +emit20240801t081306 +emit20240801t081359 +emit20240801t081411 +emit20240801t081423 +emit20240801t081544 +emit20240801t081608 +emit20240801t094728 +emit20240801t094827 +emit20240801t094839 +emit20240801t111159 +emit20240801t111211 +emit20240801t111223 +emit20240801t111235 +emit20240801t111906 +emit20240801t111930 +emit20240801t111953 +emit20240801t112005 +emit20240801t112017 +emit20240801t112029 +emit20240801t112256 +emit20240801t112425 +emit20240801t125504 +emit20240801t125516 +emit20240801t141619 +emit20240801t141631 +emit20240801t141643 +emit20240801t141903 +emit20240801t143344 +emit20240801t143424 +emit20240801t143448 +emit20240801t143500 +emit20240801t155329 +emit20240801t172608 +emit20240801t172729 +emit20240801t172741 +emit20240801t172817 +emit20240801t172829 +emit20240801t173003 +emit20240801t173015 +emit20240801t173027 +emit20240801t173102 +emit20240801t173336 +emit20240801t173424 +emit20240801t173435 +emit20240801t173546 +emit20240801t190330 +emit20240801t190342 +emit20240801t190405 +emit20240801t190453 +emit20240801t190505 +emit20240801t190516 +emit20240801t190540 +emit20240801t190616 +emit20240801t190627 +emit20240801t190639 +emit20240801t190651 +emit20240801t190802 +emit20240801t190925 +emit20240801t190937 +emit20240801t191036 +emit20240801t204050 +emit20240801t204102 +emit20240801t204125 +emit20240801t204149 +emit20240801t204213 +emit20240801t204248 +emit20240801t204312 +emit20240801t204423 +emit20240801t204435 +emit20240801t221815 +emit20240801t221826 +emit20240801t221838 +emit20240801t221902 +emit20240801t221926 +emit20240801t221937 +emit20240901t000431 +emit20240901t012911 +emit20240901t012923 +emit20240901t013057 +emit20240901t013502 +emit20240901t013514 +emit20240901t013549 +emit20240901t013601 +emit20240901t013625 +emit20240901t013648 +emit20240901t013700 +emit20240901t030529 +emit20240901t030553 +emit20240901t030605 +emit20240901t073702 +emit20240901t073738 +emit20240901t073750 +emit20240901t073837 +emit20240901t073849 +emit20240901t074129 +emit20240901t074141 +emit20240901t074153 +emit20240901t074204 +emit20240901t091942 +emit20240901t092017 +emit20240901t121513 +emit20240901t121855 +emit20240901t135121 +emit20240901t135319 +emit20240901t135331 +emit20240901t135406 +emit20240901t135442 +emit20240901t153038 +emit20240901t153050 +emit20240901t153101 +emit20240901t153113 +emit20240901t153125 +emit20240901t153201 +emit20240901t153212 +emit20241101t092349 +emit20241101t092413