Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readme and methods adjustment #19

Merged
merged 8 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 94 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Antes de usar la herramienta segurese de realizar lo siguiente:

## Uso

### Crear colección
### Preparacion

<details>
<summary>Preparación de los insumos</summary>
Expand All @@ -60,24 +60,101 @@ Para crear una colección siga los siguientes pasos:

1. Cargar la carpeta de la colección en el directorio `input`, esta carpeta debe contar con los archivos correpondientes a las capas (.tif) y el archivo mencionado previamente en la sección `Preparación de los insumos` que describe la colección en formato JSON y siempre debe ser nombrado `collection.json`.

1. Ejecutar el script de carga de la siguiente forma:
```
python src/main.py -f folder_name -c collection_name
```
Tenga en cuenta los siguientes parámetros:
- -f, --folder # Directorio dentro de input que contiene el archivo collection.json y los archivos correspondientes a las capas
- -c, --collection (opcional) # Nombre de la colección, si no se establece se toma como nombre el id definido en el archivo collection.json
- -v, --validate-only (opcional) # Si es verdadero únicamente se valida la colección pero no se carga
- -o, --overwrite (opcional) # Sobrescribe una colección ya existente
---

### Eliminar coleccion
# Instrucciones de Uso

1. Ejecutar el script de eliminacion de la coleccion
```
python src/main.py --remove-collection LossPersistance
```
Tenga en cuenta los siguientes parámetros
- --remove-collection # Comando para remover la coleccion del azure
## Cargar una Colección

Para cargar una colección de capas, ejecuta el siguiente comando:

```
python src/main.py create -f folder_name [-c collection_name] [-o]
```

### Parámetros:
- `-f, --folder` (obligatorio): Directorio con el archivo collection.json y las capas.
- `-c, --collection` (opcional): Nombre de la colección. Si no se proporciona, se tomará el id del archivo collection.json.

### Ejemplo:

* Especificando un nombre de colección
```
python src/main.py create -f my_folder -c MyCollection

o

python src/main.py create --folder my_folder --collection MyCollection

```

Este comando creará la colección `MyCollection` a partir de los archivos en el directorio `input/my_folder`

* Usando el id del archivo collection.json:

```
python src/main.py create -f my_folder

o

python src/main.py create --folder my_folder

```
---

## Validar una Colección
cazapatamar marked this conversation as resolved.
Show resolved Hide resolved

Si solo deseas validar una colección sin cargarla, puedes ejecutar:

```
python src/main.py validate -f folder_name [-c collection_name]
```

### Parámetros:
- `-f, --folder` (obligatorio): Directorio que contiene los archivos de la colección.
- `-c, --collection` (opcional): Nombre de la colección para validar. Si no se proporciona, se tomará el id del archivo collection.json.

### Ejemplo:

```
python src/main.py validate -f my_folder

o

python src/main.py validate --folder my_folder

```

Este comando validará los archivos de la colección en el directorio `input/my_folder` sin cargarlos.

---

## Eliminar una Colección

Para eliminar una colección de STAC y de Azure, ejecuta el siguiente comando:

```
python src/main.py remove --collection collection_name
```

### Parámetros:

- `-c, --collection` (obligatorio): Nombre de la colección a eliminar.

### Ejemplo:

```
python src/main.py remove -c my_collection

o

python src/main.py remove --collection my_collection

```

Este comando eliminará la colección `my_collection` del sistema.

---

## Revisión y formato de estilos para el código

Expand Down
22 changes: 11 additions & 11 deletions spec/collection.example.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "colombia_pp",
"id": "LossPersistence",
"title": "Time series of the binary presence of forests in Colombia",
"description": "Time series of the binary presence of forests in Colombia. Bosque/Non Bosque. With 1 indicating the presence of forests.",
"metadata": {
Expand All @@ -11,32 +11,32 @@
},
"items": [
{
"id": "Colombia_pp_2000-2005",
"id": "2000-2005",
"year": "2005",
"assets": {
"input_file": "Colombia_pp_2000-2005.tif"
"input_file": "2000-2005.tif"
}
},
{
"id": "Colombia_pp_2006-2010",
"id": "2006-2010",
"year": "2010",
"assets": {
"input_file": "Colombia_pp_2006-2010.tif"
"input_file": "2006-2010.tif"
}
},
{
"id": "Colombia_pp_2011-2015",
"id": "2011-2015",
"year": "2015",
"assets": {
"input_file": "Colombia_pp_2011-2015.tif"
"input_file": "2011-2015.tif"
}
},
{
"id": "Colombia_pp_2016-2021",
"year": "2010",
"id": "2016-2021",
"year": "2021",
"assets": {
"input_file": "Colombia_pp_2016-2021.tif"
"input_file": "2016-2021.tif"
}
}
]
}
}
26 changes: 20 additions & 6 deletions src/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def create_collection(self, collection_name, collection_data):
extent=pystac.Extent(
spatial=spatial_extent, temporal=temporal_extent
),
extra_fields={
"metadata": collection_data["metadata"]
},
)

self.stac_collection.validate()
Expand Down Expand Up @@ -156,12 +159,11 @@ def remove_collection(self, collection_name=None):
items_collection = stac_rest.get(f"{collection_url}/items").json()
for item in items_collection["features"]:
for asset_key, asset_value in item["assets"].items():
parsed_url = parse.urlparse(asset_value["href"])
blob_url = parsed_url.path.split("/")[-1]
url = asset_value["href"]
logger.info(
f"Deleting file: {blob_url} from Azure Blob Storage"
f"Deleting file: {url} from Azure Blob Storage"
)
self.storage.remove_file(blob_url)
self.storage.remove_file(url)

stac_rest.delete(collection_url)
logger.info(f"Collection {collection_id} removed successfully")
Expand All @@ -175,20 +177,32 @@ def upload_collection(self):
Upload the collection and items to the STAC server.
"""
try:
logger.info(
f"Uploading collection: {self.stac_collection.to_dict()}"
)

stac_rest.post_or_put(
parse.urljoin(self.stac_url, "/collections"),
self.stac_collection.to_dict(),
)
logger.info(
f"Collection {self.stac_collection.id} uploaded successfully"
)

for item in self.stac_items:
stac_rest.post_or_put(
item_dict = item.to_dict()
item_response = stac_rest.post_or_put(
parse.urljoin(
self.stac_url,
f"/collections/{self.stac_collection.id}/items",
),
item.to_dict(),
item_dict,
)
logger.info(
f"Item upload response: {item_response.status_code}"
)
except Exception as e:
logger.error(f"Error uploading collection: {e}")
raise RuntimeError(f"Error uploading collection: {e}")

def convert_layers(self, input_dir, output_dir):
Expand Down
22 changes: 12 additions & 10 deletions src/utils/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ def validate_format(data):
"""
with open("spec/collection.json", "r") as f:
schema = load(f)

try:
validate(instance=data, schema=schema)
metadata_properties_lengths = [
len(data["metadata"]["properties"][key])
for key in data["metadata"]["properties"]
]
if not len(set(metadata_properties_lengths)) == 1:
raise FormatError(
"Los elementos de la propiedad metadata properties no tienen "
"la misma longitud."
)

if "metadata" in data and "properties" in data["metadata"]:
metadata_properties_lengths = [
len(data["metadata"]["properties"][key])
for key in data["metadata"]["properties"]
]
if len(set(metadata_properties_lengths)) != 1:
raise FormatError(
"Error en las propiedades de la colección: "
"Los elementos dentro de 'metadata.properties' no tienen la misma longitud."
)

except Exception as e:
raise FormatError(
f"El archivo no cumple con el formato JSON. Detalles: {e}"
Expand Down
17 changes: 11 additions & 6 deletions src/utils/stac_rest.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import requests

from utils.logging_config import logger


def post_or_put(url: str, data: dict):
"""
Post or put data to url
"""
try:
response = requests.post(url, json=data)

if response.status_code == 409:
response = requests.put(url, json=data)

response = requests.post(url, json=data)
if response.status_code == 409:
response = requests.put(url, json=data)
if not response.status_code == 404:
response.raise_for_status()
else:
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
logger.error(f"Error during post or put: {e}")
raise e


def get(url: str):
Expand Down
22 changes: 22 additions & 0 deletions src/utils/storage.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from urllib import parse

from azure.storage.blob import BlobServiceClient

from config import get_settings

from utils.logging_config import logger


class Storage:

Expand Down Expand Up @@ -28,6 +33,23 @@ def remove_file(self, file_path):
"""
Remove a blob from Azure Blob Storage
"""
if file_path.startswith("https://"):
parsed_url = parse.urlparse(file_path)
file_path = parsed_url.path.lstrip("/")

container_name = self.container_client.container_name

if file_path.startswith(f"{container_name}/"):
file_path = file_path[len(f"{container_name}/") :]

denarch22 marked this conversation as resolved.
Show resolved Hide resolved
blob_client = self.container_client.get_blob_client(file_path)

if blob_client.exists():
blob_client.delete_blob()
logger.info(
f"Successfully deleted {file_path} from Azure Blob Storage."
)
else:
logger.warning(
f"Blob {file_path} does not exist in Azure Blob Storage."
)