mirror of
https://github.com/Alex38Lyon/Synthese-PSM_LARRA.git
synced 2026-06-01 22:00:53 +00:00
pyCreateTh
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
|
||||
# Base de données Topographiques des systèmes karstiques du massif de la Pierre Saint Martin - Larra
|
||||
|
||||
Ce dépôt contient les données topographiques et les dessins associés des cavités du massif de la Pierre Saint Martin - Larra.
|
||||
|
||||
Ce dépôt est mis à jour à chaque fois qu'une nouvelle topographie est rajoutée à l'un des systèmes décrits dans cette base de données.
|
||||
|
||||
Si besoin, des templates pour Therion sont disponibles sur [https://github.com/robertxa/Th-Config-Xav](https://github.com/robertxa/Th-Config-Xav).
|
||||
|
||||
## Description
|
||||
|
||||
Ce dépôt est en cours de développement et a pour objectif de sauvegarder et partager les données topographiques chiffrées et dessinées au format [Therion](https://therion.speleo.sk/).
|
||||
Ce travail est réalisé par les membres de l'ARSIP, collectif d'exploration du massif de la Pierre Saint Martin.
|
||||
|
||||
<p align="center">
|
||||
<a href="http://arsip.fr/">
|
||||
<img src="/Logos/Logo-ARSIP-Synthese-Topo.jpg" alt="Logo ARSIP" width="200px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Une convention a aussi été mise en place pour la gestion des points d'interrogation, avec la définition des différents champs :
|
||||
|
||||
- **Champ "Code"** : décrit le type de terminus. Il peut prendre les valeurs :
|
||||
- `A` : il suffit d'y aller et de continuer, pas d'obstacles
|
||||
- `D` : Désobstruction nécessaire
|
||||
- `E` : Escalade nécessaire
|
||||
- `P` : Puits non descendu
|
||||
- `Q` : non renseigné sur les topographies anciennes, c'est à voir/vérifier
|
||||
- `S` : Siphon à plonger
|
||||
- `T` : Trémie à désobstruer
|
||||
|
||||
- **Champ "Cavite"** : nom de la cavité concernée
|
||||
- **Champ "Reseau"** : partie de la cavité où se situe le point d'interrogation (pour le localiser rapidement sur les topographies)
|
||||
- **Champ "CA"** : rempli s'il y a présence de courant d'air, avec éventuellement des remarques/commentaires
|
||||
|
||||
**Exemple** :
|
||||
```text
|
||||
point 3922.0 1660.0 continuation -attr code Q -attr Cavite "GL102" -attr reseau "Grand Chao" -text "Rivière à topographier" -attr CA "inconnu"
|
||||
```
|
||||
|
||||
## Licence
|
||||
|
||||
L'ensemble de ces données est publié sous la licence libre Creative Commons CC BY-NC-ND 4.0 (Attribution, partage à l'identique et pas d'utilisation commerciale) :
|
||||
[https://creativecommons.org/licenses/by-nc-nd/4.0/](https://creativecommons.org/licenses/by-nc-nd/4.0/)
|
||||
|
||||
<p align="center">
|
||||
<a href="https://creativecommons.org/licenses/by-nc-nd/4.0/">
|
||||
<img src="https://mirrors.creativecommons.org/presskit/buttons/88x31/png/by-nc-nd.png" alt="Licence CC BY-NC-ND" width="100px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Auteur de la base de données
|
||||
|
||||
Alexandre PONT (<alexandre dot pont at yahoo dot fr>) pour le compte de l'ARSIP
|
||||
|
||||
## Contact
|
||||
|
||||
Pour plus d'informations, vous pouvez contacter l'ARSIP : [https://www.arsip.fr/contactez-nous](https://www.arsip.fr/contactez-nous)
|
||||
|
||||
## Remerciements
|
||||
|
||||
Cette base de données est construite sur le modèle de celle des [massifs du Folly et de Criou](https://github.com/robertxa/Topographies-Samoens_Folly), développée par Xavier Robert,
|
||||
un grand merci pour le soutien actif.
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
Base de données Topographiques des systèmes karstiques du massif de la Pierre Saint Martin - Larra
|
||||
==========================================================================================================
|
||||
|
||||
Ce dépôt contient les données topographiques et les dessins associés des cavités du massif de la Pierre Saint Martin - Larra .
|
||||
|
||||
Ce dépôt est mis à jour à chaque fois qu'une nouvelle topographie est rajoutée à l'un des systèmes décrit dans cette base de données.
|
||||
|
||||
Si besoin, des templates pour Therion sont disponibles sur https://github.com/robertxa/Th-Config-Xav .
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Ce dépôt est en cours de développement et a pour objectif de sauvegarder et partager les données topographiques chiffrées et dessinées au format `Therion <https://therion.speleo.sk/>`_.
|
||||
Ce travail est réalisé par les menbres de l'ARSIP, collectif d'exploration du massif de la pierre Saint Martin
|
||||
|
||||
.. image:: /Logos/Logo-ARSIP-Synthese-Topo.jpg
|
||||
:target: http://arsip.fr/
|
||||
:align: center
|
||||
:width: 200px
|
||||
|
||||
|
||||
|
||||
Une convention a aussi été mise en place pour la gestion des points d'interrogation, avec la définition des différents champs :
|
||||
|
||||
* le champ "Code" qui décrit le type de terminus. Il peut prendre les valeurs :
|
||||
|
||||
* A : il suffit d'y aller et de continuer, pas d'obstacles
|
||||
|
||||
* D : Désobstruction nécessaire,
|
||||
|
||||
* E : Escalade nécessaire,
|
||||
|
||||
* P : Puits non descendu,
|
||||
|
||||
* Q : non renseigné sur les topographies anciennes, c'est à voir/vérifier,
|
||||
|
||||
* S : Siphon à plonger,
|
||||
|
||||
* T : Trémie à désobstruer
|
||||
|
||||
* le champ "Cavite" qui donne le nom de la cavité en question,
|
||||
|
||||
* le champ "Reseau" qui indique la partie de la cavité où se situe le point d'interrogation (pour pouvoir le retrouver plus rapidement sur les topographies),
|
||||
|
||||
* le champ "CA" qui est rempli si présence de courant d'air, avec éventuellement des remarques/commentaires.
|
||||
|
||||
Exemple :
|
||||
point 3922.0 1660.0 continuation -attr code Q -attr Cavite "GL102" -attr reseau "Grand Chao" -text "Rivière à topographier" -attr CA "inconnu"
|
||||
|
||||
Licence
|
||||
-------
|
||||
|
||||
L'ensemble de ces données est publié sous la licence libre Creative Commons CC BY-NC-ND 4.0 (Attribution, partage à l'identique et pas d'utilisation commerciale) :
|
||||
https://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||
|
||||
.. image:: https://mirrors.creativecommons.org/presskit/buttons/88x31/png/by-nc-nd.png
|
||||
:align: center
|
||||
:width: 100px
|
||||
:target: https://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||
|
||||
Auteur de la base de données
|
||||
----------------------------
|
||||
|
||||
Alexandre PONT (alexandre dot pont at yahoo dot fr ) pour le compte de l'ARSIP
|
||||
|
||||
Contact
|
||||
--------
|
||||
|
||||
Pour plus d'informations, vous pouvez contacter L'ARSIP : https://www.arsip.fr/contactez-nous
|
||||
|
||||
Remerciements
|
||||
-------------
|
||||
|
||||
Cette base de données est construite sur le modèle de celle des `massifs du Folly et de Criou <https://github.com/robertxa/Topographies-Samoens_Folly>`_, développée par Xavier Robert
|
||||
), un grand merci pour le soutien actif
|
||||
Binary file not shown.
Binary file not shown.
@@ -249,7 +249,7 @@ def read_config(config_file):
|
||||
global_data.stationNamesInTh2 = bool(config['Application_Data']['station_name_in_th2_files'])
|
||||
|
||||
if 'Application_Data' in config and 'kSmooth' in config['Application_Data']:
|
||||
global_data.therionPath = float(config['Application_Data']['kSmooth'])
|
||||
global_data.kSmooth = float(config['Application_Data']['kSmooth'])
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ def compile_template(template, template_args, totReadMeError = "", **kwargs ):
|
||||
try:
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
config = template.format(**template_args, tmpdir=tmpdir.replace("\\", "/"))
|
||||
|
||||
|
||||
|
||||
log.debug(f"{config}\n")
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ therion_path = C:\Program Files\Therion\therion.exe
|
||||
survey_prefix_name = Explo_
|
||||
|
||||
# Options for Th2 files
|
||||
shot_lines_in_th2_files = True
|
||||
station_name_in_th2_files = True
|
||||
shot_lines_in_th2_files = False
|
||||
station_name_in_th2_files = False
|
||||
wall_lines_in_th2_files = False
|
||||
|
||||
# Koef for smoothing wall
|
||||
|
||||
@@ -42,12 +42,13 @@ En cours :
|
||||
|
||||
"""
|
||||
|
||||
Version = "2025.07.01"
|
||||
Version = "2025.07.02"
|
||||
|
||||
#################################################################################################
|
||||
#################################################################################################
|
||||
import os, re, argparse, shutil, sys, time, math
|
||||
from os.path import isfile, join, abspath, splitext
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import networkx as nx
|
||||
import pandas as pd
|
||||
@@ -423,7 +424,7 @@ def parse_xvi_file(th_name_xvi):
|
||||
return stations, lines, splays, x_min, x_max, y_min, y_max, x_ecart, y_ecart
|
||||
|
||||
#################################################################################################
|
||||
def assign_groups_and_ranks(df_lines):
|
||||
def assign_groups_and_ranks_Old(df_lines):
|
||||
G = nx.Graph()
|
||||
for _, row in df_lines.iterrows():
|
||||
G.add_edge(row["name1"], row["name2"])
|
||||
@@ -483,6 +484,9 @@ def assign_groups_and_ranks(df_lines):
|
||||
df_equates["group_id"] = df_equates["group_id"].astype(int)
|
||||
df_equates["start_point"] = df_equates["start_point"].astype(str)
|
||||
df_equates["end_point"] = df_equates["end_point"].astype(str)
|
||||
|
||||
print("df_result columns:", df_result.columns)
|
||||
print("df_result empty:", df_result.empty)
|
||||
|
||||
# Ajout de la colonne max_rank
|
||||
max_ranks = df_result.groupby("group_id")["rank_in_group"].max().reset_index()
|
||||
@@ -501,6 +505,92 @@ def assign_groups_and_ranks(df_lines):
|
||||
|
||||
return df_result, df_equates
|
||||
|
||||
def assign_groups_and_ranks(df_lines):
|
||||
G = nx.Graph()
|
||||
for _, row in df_lines.iterrows():
|
||||
G.add_edge(row["name1"], row["name2"])
|
||||
|
||||
used_edges = set()
|
||||
results = []
|
||||
equates = [] # Liste des (group_id, start_point, end_point)
|
||||
group_id = 0
|
||||
|
||||
def walk_path(u, prev=None):
|
||||
path = []
|
||||
current = u
|
||||
while True:
|
||||
neighbors = [n for n in G.neighbors(current) if n != prev]
|
||||
if len(neighbors) != 1:
|
||||
break
|
||||
next_node = neighbors[0]
|
||||
edge = tuple(sorted((current, next_node)))
|
||||
if edge in used_edges:
|
||||
break
|
||||
used_edges.add(edge)
|
||||
path.append(edge)
|
||||
prev = current
|
||||
current = next_node
|
||||
return path
|
||||
|
||||
# Noeuds ayant un degré différent de 2
|
||||
start_nodes = [n for n in G.nodes if G.degree(n) != 2]
|
||||
|
||||
# Si tous les nœuds ont un degré 2 : cycle fermé
|
||||
if not start_nodes:
|
||||
start_nodes = [list(G.nodes)[0]]
|
||||
|
||||
for node in start_nodes:
|
||||
for neighbor in G.neighbors(node):
|
||||
edge = tuple(sorted((node, neighbor)))
|
||||
if edge in used_edges:
|
||||
continue
|
||||
used_edges.add(edge)
|
||||
path = [(node, neighbor)] + walk_path(neighbor, node)
|
||||
|
||||
for rank, (n1, n2) in enumerate(path):
|
||||
match = df_lines[(df_lines["name1"] == n1) & (df_lines["name2"] == n2)]
|
||||
if match.empty:
|
||||
match = df_lines[(df_lines["name1"] == n2) & (df_lines["name2"] == n1)]
|
||||
if not match.empty:
|
||||
row = match.iloc[0].copy()
|
||||
row["group_id"] = group_id
|
||||
row["rank_in_group"] = rank
|
||||
results.append(row)
|
||||
if rank == 0:
|
||||
start_point = n1
|
||||
end_point = path[-1][1] if path else start_point
|
||||
equates.append((group_id, str(start_point), str(end_point)))
|
||||
group_id += 1
|
||||
|
||||
# Création du DataFrame principal
|
||||
df_result = pd.DataFrame(results)
|
||||
|
||||
# Création du DataFrame equates
|
||||
df_equates = pd.DataFrame(equates, columns=["group_id", "start_point", "end_point"])
|
||||
df_equates["group_id"] = df_equates["group_id"].astype(int)
|
||||
df_equates["start_point"] = df_equates["start_point"].astype(str)
|
||||
df_equates["end_point"] = df_equates["end_point"].astype(str)
|
||||
|
||||
# Ajout de la colonne max_rank (si possible)
|
||||
if not df_result.empty and "group_id" in df_result.columns:
|
||||
max_ranks = df_result.groupby("group_id")["rank_in_group"].max().reset_index()
|
||||
max_ranks.rename(columns={"rank_in_group": "max_rank"}, inplace=True)
|
||||
max_ranks["max_rank"] = max_ranks["max_rank"].astype(int)
|
||||
df_equates = df_equates.merge(max_ranks, on="group_id", how="left")
|
||||
else:
|
||||
df_equates["max_rank"] = 0
|
||||
|
||||
# Ajout de la colonne start_group (raccord logique avec un autre groupe)
|
||||
end_to_group = df_equates[["end_point", "group_id"]].copy()
|
||||
end_to_group.rename(columns={"end_point": "start_point", "group_id": "start_group"}, inplace=True)
|
||||
end_to_group["start_point"] = end_to_group["start_point"].astype(str)
|
||||
df_equates = df_equates.merge(end_to_group, on="start_point", how="left")
|
||||
|
||||
# Remplacer les NaN dans start_group par 0
|
||||
df_equates["start_group"] = df_equates["start_group"].fillna(0).astype(int)
|
||||
|
||||
return df_result, df_equates
|
||||
|
||||
|
||||
#################################################################################################
|
||||
def add_start_end_splays(df_splays_complet, df_equates):
|
||||
@@ -560,7 +650,7 @@ def add_start_end_splays(df_splays_complet, df_equates):
|
||||
return df_splays_new
|
||||
|
||||
|
||||
|
||||
#################################################################################################
|
||||
def align_points(smoothX1, smoothY1, X, Y, smoothX2, smoothY2):
|
||||
# Vecteurs d'origine vers smooth1 et smooth2
|
||||
dx1, dy1 = smoothX1 - X, smoothY1 - Y
|
||||
@@ -591,7 +681,6 @@ def align_points(smoothX1, smoothY1, X, Y, smoothX2, smoothY2):
|
||||
return (_smoothX1, _smoothY1), (_smoothX2, _smoothY2)
|
||||
|
||||
|
||||
|
||||
#################################################################################################
|
||||
def wall_construction_smoothed(df_lines, df_splays, x_min, x_max, y_min, y_max):
|
||||
|
||||
@@ -610,7 +699,6 @@ def wall_construction_smoothed(df_lines, df_splays, x_min, x_max, y_min, y_max):
|
||||
if len(df_lines) <= 2 or len(df_splays) <= 2:
|
||||
return th2_walls, 0, 0, 0, 0
|
||||
|
||||
|
||||
df_lines, df_equates = assign_groups_and_ranks(df_lines)
|
||||
|
||||
# Conversion en polaire
|
||||
@@ -969,7 +1057,6 @@ def create_th_folders(ENTRY_FILE,
|
||||
if not survey:
|
||||
raise NoSurveysFoundException(f"No survey found with that selector")
|
||||
|
||||
|
||||
if UPDATE :
|
||||
DEST_PATH = os.path.dirname(args.file)
|
||||
log.info(f"Update th2 files: {Colors.ENDC}{DEST_PATH}")
|
||||
@@ -984,7 +1071,6 @@ def create_th_folders(ENTRY_FILE,
|
||||
log.debug(f"\t{Colors.BLUE}DEST_PATH: {Colors.ENDC} {DEST_PATH}")
|
||||
log.debug(f"\t{Colors.BLUE}ABS_PATH: {Colors.ENDC} {ABS_PATH}")
|
||||
|
||||
|
||||
#################################################################################################
|
||||
# Copy template folders #
|
||||
#################################################################################################
|
||||
@@ -1000,20 +1086,19 @@ def create_th_folders(ENTRY_FILE,
|
||||
log.info(f"Compiling 2D XVI file: {Colors.ENDC}{TH_NAME}")
|
||||
|
||||
if UPDATE:
|
||||
template_args = {
|
||||
"th_file": DEST_PATH + "/" + TH_NAME + ".th",
|
||||
"selector": survey.therion_id,
|
||||
"th_name": DEST_PATH + "/" + TH_NAME,
|
||||
"scale": int(int(SCALE)/10),
|
||||
}
|
||||
thFile = Path(DEST_PATH + "\\" + TH_NAME + ".th")
|
||||
thName = Path(DEST_PATH + "\\" + TH_NAME)
|
||||
|
||||
else :
|
||||
template_args = {
|
||||
"th_file": DEST_PATH + "/Data/" + TH_NAME + ".th",
|
||||
thFile = Path(DEST_PATH + "\\Data\\" + TH_NAME + ".th")
|
||||
thName = Path(DEST_PATH + "\\Data\\" + TH_NAME)
|
||||
|
||||
template_args = {
|
||||
"th_file": thFile,
|
||||
"selector": survey.therion_id,
|
||||
"th_name": DEST_PATH + "/Data/" + TH_NAME,
|
||||
"th_name": thName,
|
||||
"XVIscale": globalData.XVIScale,
|
||||
}
|
||||
}
|
||||
|
||||
logfile, tmpdir, totReadMeError = compile_template(globalData.thconfigTemplate, template_args, totReadMeError, cleanup=False, therion_path=globalData.therionPath)
|
||||
|
||||
@@ -1026,8 +1111,7 @@ def create_th_folders(ENTRY_FILE,
|
||||
else :
|
||||
flagErrorCompile = False
|
||||
stat = get_stats_from_log(logfile)
|
||||
|
||||
|
||||
|
||||
#################################################################################################
|
||||
# Update files #
|
||||
#################################################################################################
|
||||
@@ -1508,7 +1592,7 @@ def mak_to_th_file(ENTRY_FILE) :
|
||||
|
||||
for file in datFiles :
|
||||
ABS_file = os.path.dirname(abspath(args.file)) + "\\"+ file
|
||||
content, val = load_text_file_utf8(ABS_file, os.path.basename(ABS_file))
|
||||
content, val, encodage = load_text_file_utf8(ABS_file, os.path.basename(ABS_file))
|
||||
section = content.split('\x0c')
|
||||
QtySections += len(section)
|
||||
|
||||
@@ -1553,9 +1637,9 @@ def mak_to_th_file(ENTRY_FILE) :
|
||||
for file in datFiles:
|
||||
|
||||
if globalData.error_count > 0:
|
||||
bar.text(f"{Colors.INFO}, file: {Colors.ENDC}{file[:-4]}{Colors.ERROR}, error: {Colors.ENDC}{globalData.error_count}")
|
||||
bar.text(f"{Colors.INFO}file: {Colors.ENDC}{file[:-4]}{Colors.ERROR}, error: {Colors.ENDC}{globalData.error_count}")
|
||||
else :
|
||||
bar.text(f"{Colors.INFO}, file: {Colors.ENDC}{file[:-4]}")
|
||||
bar.text(f"{Colors.INFO}file: {Colors.ENDC}{file[:-4]}")
|
||||
|
||||
_file = os.path.dirname(abspath(args.file)) + "\\" + file
|
||||
shutil.copy(_file, folderDest + "\\Data\\")
|
||||
@@ -2798,9 +2882,9 @@ def dat_to_th_files (ENTRY_FILE, fixPoints = [], crs_wkt = "", CONFIG_PATH = "",
|
||||
surveyCount += 1
|
||||
|
||||
if globalData.error_count > 0:
|
||||
bar.text(f"{Colors.INFO}, file: {Colors.ENDC}{os.path.basename(ENTRY_FILE)[:-4]}{Colors.INFO}, survey: {Colors.ENDC}{currentSurveyName}{Colors.ERROR}, error: {Colors.ENDC}{globalData.error_count}")
|
||||
bar.text(f"{Colors.INFO}file: {Colors.ENDC}{os.path.basename(ENTRY_FILE)[:-4]}{Colors.INFO}, survey: {Colors.ENDC}{currentSurveyName}{Colors.ERROR}, error: {Colors.ENDC}{globalData.error_count}")
|
||||
else :
|
||||
bar.text(f"{Colors.INFO}, file: {Colors.ENDC}{os.path.basename(ENTRY_FILE)[:-4]}{Colors.INFO}, survey: {Colors.ENDC}{currentSurveyName}")
|
||||
bar.text(f"{Colors.INFO}file: {Colors.ENDC}{os.path.basename(ENTRY_FILE)[:-4]}{Colors.INFO}, survey: {Colors.ENDC}{currentSurveyName}")
|
||||
bar()
|
||||
|
||||
#################################################################################################
|
||||
@@ -3081,9 +3165,9 @@ if __name__ == u'__main__':
|
||||
with redirect_stdout(sys.__stdout__):
|
||||
for i in range(1):
|
||||
if globalData.error_count > 0:
|
||||
bar.text(f"{Colors.INFO}, file: {Colors.ENDC}{os.path.basename(ABS_file)[:-4]}{Colors.ERROR}, error: {Colors.ENDC}{globalData.error_count}")
|
||||
bar.text(f"{Colors.INFO}file: {Colors.ENDC}{os.path.basename(ABS_file)[:-4]}{Colors.ERROR}, error: {Colors.ENDC}{globalData.error_count}")
|
||||
else :
|
||||
bar.text(f"{Colors.INFO}, file: {Colors.ENDC}{os.path.basename(ABS_file)[:-4]}")
|
||||
bar.text(f"{Colors.INFO}file: {Colors.ENDC}{os.path.basename(ABS_file)[:-4]}")
|
||||
stationList, fileTitle, totReadMeError, thread2 = dat_to_th_files (ABS_file , fixPoints = [], crs_wkt = "", CONFIG_PATH = _ConfigPath, totReadMeError = "", bar = bar)
|
||||
threads += thread2
|
||||
bar()
|
||||
|
||||
Reference in New Issue
Block a user