pyCreateTh

This commit is contained in:
Alex38Lyon
2025-07-01 16:17:33 +02:00
parent 318dbad6ca
commit 77d57d67dc
27 changed files with 3133 additions and 84 deletions
@@ -0,0 +1,28 @@
######!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import division
# This to be sure that the result of the division of integers is a real, not an integer
from __future__ import absolute_import
from __future__ import print_function
# Import modules
import sys
import os
from . _version import __version__
# Import all the functions
__all__ = ['vtopotools', 'datathwritetools', 'buildthconfig', 'buildthconfig', 'tro2th.tro2th']
#from .text import joke
#from datathwritetools import writeheader_th, writecenterlineheader, writedata
from .buildparam import *
from .vtopotools import *
from .datathwritetools import *
from .buildthconfig import *
from .tro2th import *
@@ -0,0 +1,4 @@
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
__version__ = "1.3.0"
@@ -0,0 +1,4 @@
#!/usr/bin/env python
import .....
print tro2therion()
@@ -0,0 +1,95 @@
######!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Script to build Therion files
By Xavier Robert
Lima, 2016.06.21
USAGE :
1- Run in the terminal: $ python buildthconfig.py
INPUTS:
The inputs are in the script file, in the "# Define data to analysis" section.
The different arguments are described.
"""
###### To DO : #######
# -
###### End To DO #######
from __future__ import division
# This to be sure that the result of the division of integers is a real, not an integer
# Import modules
import sys
import os
import copy
########################
def builddictcave():
"""
"""
########################
# Define parameters
# thlang: language to set in the files, can be english [en] or french [fr]
thlang = 'fr'
# thcfile: set to True to build a config file, or False if not
thcfile = True
# thcfnme: name of the thc file
thcfnme = 'config.thc'
# thcpath: path where to add the config file.
# if None, it will be in the folder from where is run the code
thcpath = None
# thconfigfile: set to True to build a thconfig file, or False if not
thconfigfile = True
# thconfigpath: path where to add the thconfig file.
# if None, it will be in the folder from where is run the code
thconfigpath = None
# thconfigfnme: name of the thconfig file
thconfigfnme= 'Test.thconfig'
#icomments: True if we add comments inside the thconfig file,
# False if there is no comments inside the thconfig file
icomments = True
#icoupe: True if we want a layout for extended projection in the thconfig
# False if not
icoupe = True
# Errfiles: True to write on previous files; be careful in that case !!
# False if not
Errfiles = True
# sourcefiles: source files
sourcefile = ['example.th', 'example.th2', 'example-coupe.th2']
# xviscale: scale of the xvi file
# 1000 corresponds to 1/1000
xviscale = 1000
# xvigrid: spacing of the grid for the xvi, in meters
xvigrid = 10
# cavefnme: cave fnme
cavefnme = 'Example'
# coord: coordinate system
# Can be set to None
coord = None
# scale: scale of the map
# 500 corresponds to 1/500
scale = 500
data = [thlang, thcfile, thcfnme, thcpath,
thconfigfile, thconfigpath, thconfigfnme,
icomments, icoupe, Errfiles]
dictcave = [sourcefile, xviscale, xvigrid, cavefnme, coord, scale]
return dictcave, data
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,100 @@
######!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
import argparse
from ._version import __version__
from .tro2th import tro2th
def main(**kwargs):
ap = argparse.ArgumentParser()
ap.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
ap.add_argument(
"--fle-tro-fnme",
default=None,
help="Path and name of the .tro file to convert",
)
ap.add_argument(
"--fle-tro-encoding",
default=None,
help="Force encoding of the .tro file to convert, for instance iso-8859-1. Default is utf-8",
)
ap.add_argument(
"--fle-th-fnme",
default=None,
help="Path and name of the .th file to create from the .tro file.",
)
ap.add_argument(
"--thlang", default="fr", help="String that set the language. 'fr' by default"
)
ap.add_argument("--cavename", default=None, help="Name of the cave")
ap.add_argument(
"--no-icomments",
default=True,
action="store_const",
const=False,
dest="icomments",
help="Disable comments in the produced files",
)
ap.add_argument(
"--no-icoupe",
default=True,
action="store_const",
const=False,
dest="icoupe",
help="Disable the extended-elevation layout in the .thconfig file",
)
ap.add_argument(
"--ithconfig",
default=True,
action="store_const",
const=False,
dest="ithconfig",
help="Disable creation of the thconfig file",
)
ap.add_argument(
"--thconfigfnme", default=None, help="Path and name of the thconfig file"
)
ap.add_argument(
"--no-ithc",
default=True,
action="store_const",
const="False",
dest="ithc",
help="Disable creation of a config file config.thc",
)
ap.add_argument(
"--thcpath",
default=None,
help="Path to the directory that contains the config file called in the cave.thconfig file",
)
ap.add_argument("--thcfnme", default="config.thc", help="Name of the config.thc")
ap.add_argument(
"--sourcefile",
nargs="*",
help="Define the source files declared in the cave.thconfig",
)
ap.add_argument(
"--xviscale", default=1000, type=float, help="Scale of the xvi file"
)
ap.add_argument(
"--xvigrid",
default=10.0,
type=float,
help="Spacing of the grid for the xvi, in meters",
)
ap.add_argument("--scale", default=500, type=float, help="Scale of the map")
ap.add_argument(
"--no-error-files",
default=True,
action="store_const",
const=False,
dest="Errorfiles",
help="Do not raise en error if output files exists in the folder",
)
args = ap.parse_args(**kwargs)
tro2th(**vars(args))
@@ -0,0 +1,569 @@
######!/usr/bin/env python
# -*- coding: utf-8 -*-
# coding: utf8
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
# Modifié Alex 2025 07 01
"""
Script to build Therion files
By Xavier Robert
Lima, 2016.06.21
USAGE :
1- Run in the terminal: $ python buildthconfig.py
INPUTS:
The inputs are in the script file, in the "# Define data to analysis" section.
The different arguments are described.
"""
###### To DO : #######
# - Test the MTL pdfs (I have not tested it, even if it should be OK)
# - Add error bars on data graphs ?
# For that we should read the input data file given in topo_parameters.txt
# (paragraphe N°12 of topo_parameters.txt)
#
###### End To DO #######
from __future__ import division
# This to be sure that the result of the division of integers is a real, not an integer
#from __future__ import unicode_literals
# Import modules
from Lib.general_fonctions import sanitize_filename
import sys, os, copy, datetime
from pyproj import Proj, transform
#################################################################################################
def writeheader_th(file, cavename, entrance):
"""
Function to write the header of the file.th
INPUTS:
file : variable that sets the file.th
cavename : name of the cave
entrance : name of the entrance station
OUTPUTS:
None
USAGE:
writeheader_th(file, cavename, entrance)
Author: Xavier Robert, Lima 2016/06/27
"""
file.write(u'encoding utf-8 \n\nsurvey %s -title "%s" -entrance "%s" \n'
%(sanitize_filename(cavename), cavename, entrance))
return
#################################################################################################
def writecenterlineheader(file, entrance, settings, comments, data, coordsyst, coordinates, club,
icomments, thlang):
"""
Function to write the centerline header
INPUTS:
file : variable that sets the file.th
entrance : name of the entrance station
settings : List of the settings of this survey section
comments : String that correspond to the end of the string "Line"
that do not correspond to the settings
data : data from this survey section
coordsyst : Coordinates system to set the entrance coordinates
coordinates : Entrance coordinates
club : Name of the group that explored the cave
icomments : True if comments in the file
False if not
thlang : 'fr' for french
'en' for english
... other languages not implemented
OUTPUTS:
None
USAGE:
writeheader_th(file, cavename, entrance)
Author: Xavier Robert, Lima 2016/06/27
"""
# First, define dictionaries to help the coding
# angleU: define the angle unit
angleU = {u'Deg' : u'degrees',
u'Degd' :u'degrees',
u'Gra' : u'grad'}
# compassdir:
dir = {u'Dir' : u'',
u'Inv' : u'back'}
# lruddir: Set the LRUD
lruddir = {u'Dir' : u'left right up down',
u'Inv' : u'right left up down',
u'Nod' : u''}
# unitcounter: set the unit of the counter (for the length)
unitcounter = {u'Vulc' : u'centi',
u'Prof' : u'',
u'Deniv': u''}
# unitclino: used to correct the clino if topoVulcain
unitclino = {u'Deg' : u'90',
u'Degd' : u'90',
u'Gra' : u'100'}
# typelen: type of length measures
#typelem = {u'Deca' : u'normal',
# u'Topof' : u'topofil',
# u'Vulc' : u'topofil',
# u'Prof' : u'diving',
# u'Deniv' : u'deniv'}
# style: data style
style = {u'Deca' : u'normal',
u'Topof' : u'topofil',
u'Diving' : u'diving',
u'Prof' : u'diving',
u'Carth' : u'carthesian',
u'Cylp' : u'cylpolar',
u'Dim' : u'dimensions',
u'Nosy' : u'nosurvey'}
# station: type of stations
station = {u'station' : u'station',
u'from' : u'from',
u'to' : u'to',
u'vtopo' : u'from to'}
# lensurv: how are set the length measurements
lensurv = {u'Deca' : u'length',
u'Topof' : u'fromcount tocount',
u'Diving' : u'length',
u'Prof' : u'length'}
# slopesurv: how are set the slope measurements
slopesurv = {u'Clino' : u'clino',
u'Vulc' : u'clino',
u'Deniv' : u'depthchange',
u'Prof' : u'depth'}
# Begin the centerline
file.write(u'\n\tcenterline \n')
# if entrance in the data, write the entrance coordinates
if [datal for datal in data if entrance in datal] != []:
if icomments:
if thlang == u'fr':
file.write(u'\t\t# Si le systeme de coordonnées n\'est pas le système'
u' Lambert français, voir le Thbook et le fichier'
u' extern/proj4/nad/epsg dans le dossier source de Therion \n')
file.write(u'\t\t# Si les coordonnées de l\'entrée sont connues,'
u' copier dans la centerline correspondante et décommenter'
u' les 2 lignes suivantes : \n')
elif thlang == u'en':
file.write(u'\t\t# If your are not in the french Lambert system, '
u' To find number of your system, see'
u' extern/proj4/nad/epsg file in the Therion'
u' source distribution \n')
file.write(u'\t\t# If the entrance coordinates are known, uncomment and'
u' copy in the corresponding centerline the next 2 lines: \n')
if coordsyst != None:
file.write(u'\t\tcs %s \n'
u'\t\tfix %s %s %s %s \n\n' % (coordsyst, entrance, coordinates[0], coordinates[0], coordinates[0]))
else:
file.write(u'\t\t#cs %s \n'
u'\t\t#fix %s %s %s %s \n\n' % (coordsyst, entrance, coordinates[0], coordinates[0], coordinates[0]))
typem = u'Deca'
if u'Topof' not in settings:
settings [1:1]= u' '
typem = u'Topof'
if u'Prof' in settings or u'Deniv' in settings:
settings[4:4] = u' '
# next line used to debug
#file.write(u'\t' + str(settings) + u'\n')
# write the survey caracteristics
file.write(u'\t\tdate %s\n'% str(settings[9]))
if icomments:
if thlang == u'fr':
file.write(u'\t\t# Si date est utilisé, commenter la ligne "declination", '
u'la date sera utilisée pour la calculer\n')
elif thlang == u'en':
file.write(u'\t\t# If date is used, comment the ligne "declination", '
u'the date will be use to compute it\n')
file.write(u'\t\tdeclination %s %s \n'% (str(settings[5]), angleU[settings[2]]))
# file.write(u'\t\t\tteam "G.S. Vulcain" \n')
file.write(u'\t\t# team "%s" \n' % club)
file.write(u'\t\t#explo-date %s\n'% str(settings[9]))
# file.write(u'\t\t\texplo-team "G.S. Vulcain" \n')
file.write(u'\t\t# explo-team "%s" \n' % club)
if icomments:
if thlang == u'en': file.write(u'\t\t# (to be completed, add many lines as you need) \n')
elif thlang == u'fr': file.write(u'\t\t# (peut être complété en ajoutant le nombre de lignes nécessaires) \n')
dirs = settings[6].rstrip(u'\n\r').split(u',')
file.write(u'\n\t\tunits length meters \n')
if u'Topof' in settings:
file.write(u'\t\tunits counter %smeters \n' % unitcounter[settings[3]])
file.write(u'\t\tcalibrate counter 0 %s \n' % settings[1])
# To set the slope
if u'Vulc' in settings:
file.write(u'\t\tcalibrate clino 1 %s -1\n' % unitclino[settings[4]])
if u'Prof' in settings:
file.write(u'\t\tunits depth meters \n')
typem = u'Prof'
elif u'Deniv' in settings:
file.write(u'\t\tunits depth meters \n')
typem = u'Diving'
file.write(u'\t\tunits compass %s \n' % (angleU[settings[2]]))
if u'Vulc' in settings or 'Clino' in settings:
file.write(u'\t\tunits clino %s \n' % (angleU[settings[4]]))
file.write(u'\n\t\tdata %s %s %s %scompass %s%s %s\n'
% (style[typem], station[u'vtopo'], lensurv[settings[0]],
dir[dirs[0]], dir[dirs[1]], slopesurv[settings[3]],
lruddir[dirs[2]]))
if comments != u'':
file.write(u'\t\t\t#' + comments + u'\n')
return
#################################################################################################
def writedata(file, settings, data, dataold):
"""
function to write the data in the .th file
INPUTS:
file : variable that sets the file.th
settings : List of the settings of this survey section
data : data from this survey section
dataold : data from the previous survey section
OUTPUTS:
None
USAGE:
writeheader_th(file, cavename, entrance)
Author: Xavier Robert, Lima 2016/06/27
"""
# dictl = length of the data line
dictl = {u'Deca' : 9,
u'Topof' : 10}
i=0
for elems in data:
for k in [0,2]:
if elems[k] == u'*':
# remove the '*', and replace them with the right data !
if i == 0: elems[k] = dataold[len(dataold)-1][k+1]
else: elems[k] = data[i-1][k+1]
if elems[0] == elems[1]: elems[1] = elems[1] + u'd'
for k in range (dictl[settings[0]]-4, dictl[settings[0]]):
# Check that LRUD != '*'; If yes, change them to 0
if elems[k] == u'*': elems[k] = u'0'
# Check if option 'E'
if u'E' in elems:
file.write(u'\t\t\tflags duplicate \n')
# We write the data
# if elems[0:1] == "*":
# elems[0:1] = "-"
file.write(u'\t\t\t' + u'\t'.join(
"-" if i == 1 and x == "*" else x
for i, x in enumerate(elems[0:dictl[settings[0]]])
))
# file.write(u'\t\t\t' + u'\t'.join(x for x in elems[0:dictl[settings[0]]]))
if len(elems) > (dictl[settings[0]] + 2):
if elems[dictl[settings[0]] + 1] != u'N' and elems[dictl[settings[0]] + 1] != u'I':
# we add the comment if there is one
file.write(u'\t# ' + ' '.join(x for x in elems[(dictl[settings[0]]+1) : len(elems)])[1:-1] + u'\n')
elif len(elems) > (dictl[settings[0]] + 3):
file.write(u'\t# ' + ' '.join(x for x in elems[(dictl[settings[0]]+2) : len(elems)])[1:-1] + u'\n')
else:
file.write(u'\n')
else:
file.write(u'\n')
if elems[(dictl[settings[0]])] == u'I':
file.write(u'\t\t\textend reverse \n')
if u'E' in elems:
file.write(u'\t\t\tflags not duplicate \n')
i+=1
return
#################################################################################################
def write_thtot(file, cavename = u'cave', icomments = True, thlang = 'en'):
"""
Function to write the file cavename-tot.th
INPUTS:
file : variable that sets the file.th
cavename : name of the cave
icomments : True if comments in the file
False if not
thlang : 'fr' for french
'en' for english
... other languages not implemented
OUTPUTS:
None
USAGE:
write_thtot(file, cavename, icomments, thlang)
Author: Xavier Robert, Grenoble 2021/01/03
"""
file.write(u'encoding utf-8 \n\n')
#file.write(u'encoding utf-8' \n\nsurvey %s -title "%s" -entrance "%s" \n'
# %(cavename.replace(u' ', u'_'), cavename, entrance))
if icomments:
if thlang == u'fr':
file.write(u'# Copyright (C) %s Xavier Robert <xavier.robert***@***ird.fr>\n' %(str(datetime.datetime.now().year)))
file.write(u'# Ce travaille est sous la licence Creative Commons Attribution-ShareAlike-NonCommecial :\n')
file.write(u'# <http://creativecommons.org/licenses/by-nc-sa/4.0/>\n\n')
elif thlang == u'en':
file.write(u'# Copyright (C) %s Xavier Robert <xavier.robert***@***ird.fr>\n' %(str(datetime.datetime.now().year)))
file.write(u'# This work is under the Creative Commons Attribution-ShareAlike-NonCommecial License:\n')
file.write(u'# <http://creativecommons.org/licenses/by-nc-sa/4.0/>\n\n')
file.write(u'survey %s -title "%s"\n\n' %(sanitize_filename(cavename), cavename.replace(u' ', u'_')))
#file.write(u'survey %s -title "%s"\n\n' %(cavename.replace(u' ', u'_'), cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr':
file.write(u'\t# Pour importer les différentes données de différents fichiers topos :\n')
if thlang == u'en':
file.write(u'\t# To import data from different data files:\n')
file.write(u'\tinput Data/%s.th\n\n' %(cavename.replace(u' ', u'_')))
file.write(u'#\tcenterline\n')
if icomments:
if thlang == u'fr': file.write(u'\t\t##Rajout des longueurs explorées, non topo, ou topos perdues\n')
elif thlang == u'en': file.write(u'\t\t##Add length explored, but not surveyed, or with lost surveys\n')
file.write(u'#\t\tstation Ca.31@%s "+78 m explorés " continuation explored 78m\n' %(cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr': file.write(u'\t\t## Pour assembler plusieurs fichiers topos\n')
elif thlang == u'en': file.write(u'\t\t## To join different surveys\n')
file.write(u'#\t\tequate 6@%s 0@%s\n\n'%(cavename.replace(u' ', u'_'), cavename.replace(u' ', u'_') + u'2'))
file.write(u'#\tendcenterline)\n\n')
if icomments:
file.write(u'#\t##########################################################################################\n')
if thlang == u'fr':
file.write(u'#\t## Pour importer les différents fichiers de dessins en plan\n')
file.write(u'#\t## Et Pour assembler plusieurs scraps entre eux, il faut utiliser la commande\n')
file.write(u"#\t## join scrap1 scrap2 -count n (où n = nombre de galerie à connecter, par défaut n = 1). C'est tout simple !\n")
elif thlang == u'en':
file.write(u'#\t## To import different th2 files\n')
file.write(u'#\t## And to join different scraps together, you need to use the command\n')
file.write(u"#\t## join scrap1 scrap2 -count n (wher n = number of connections, by default n = 1). This is simple!\n")
file.write(u'#\tjoin scrap1 scrap2 #-count n\n\n')
if icomments:
if thlang == u'fr': file.write(u'## Pour le plan\n')
elif thlang == u'en': file.write(u'## For plan view\n')
file.write(u'input Data/%s.th2\n\n' %(cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr': file.write(u'## Pour la coupe développée\n')
elif thlang == u'en': file.write(u'## For extended elevation\n')
file.write(u'input Data/%s-coupe.th2\n\n' %(cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr': file.write(u'## Appel des maps\n')
elif thlang == u'en': file.write(u'## Call the maps file\n')
file.write(u'input %s-maps.th\n\n' %(cavename.replace(u' ', u'_')))
file.write(u'endsurvey\n')
return
#################################################################################################
def write_thmaps(file, cavename = u'cave', icomments = True, thlang = 'en'):
"""
Function to write the file cavename-maps.th
INPUTS:
file : variable that sets the file.th
cavename : name of the cave
icomments : True if comments in the file
False if not
thlang : 'fr' for french
'en' for english
... other languages not implemented
OUTPUTS:
None
USAGE:
write_thmaps(file, cavename, icomments, thlang)
Author: Xavier Robert, Grenoble 2021/01/03
"""
file.write(u'encoding utf-8 \n\n')
#file.write(u'encoding utf-8' \n\nsurvey %s -title "%s" -entrance "%s" \n'
# %(cavename.replace(u' ', u'_'), cavename, entrance))
if icomments:
if thlang == u'fr':
file.write(u'# Copyright (C) %s Xavier Robert <xavier.robert***@***ird.fr>\n' %(str(datetime.datetime.now().year)))
file.write(u'# Ce travail est sous la licence Creative Commons Attribution-ShareAlike-NonCommecial :\n')
file.write(u'# <http://creativecommons.org/licenses/by-nc-sa/4.0/>\n\n')
elif thlang == u'en':
file.write(u'# Copyright (C) %s Xavier Robert <xavier.robert***@***ird.fr>\n' %(str(datetime.datetime.now().year)))
file.write(u'# This work is under the Creative Commons Attribution-ShareAlike-NonCommecial License:\n')
file.write(u'# <http://creativecommons.org/licenses/by-nc-sa/4.0/>\n\n')
file.write(u'map MP-%s-plan-tot -title "%s"\n' %(cavename.replace(u' ', u'_'), cavename.replace(u' ', u'_')))
file.write(u'\tSP-%s-1\n' %(cavename.replace(u' ', u'_')))
file.write(u'\t#break\n')
file.write(u'\t#SP-%s-2\n' %(cavename.replace(u' ', u'_')))
file.write(u'endmap\n')
file.write(u'map MC-%s-coupe-tot -title "%s"\n' %(cavename.replace(u' ', u'_'), cavename.replace(u' ', u'_')))
file.write(u'\tSC-%s-1\n' %(cavename.replace(u' ', u'_')))
file.write(u'\t#break\n')
file.write(u'\t#SC-%s-2\n' %(cavename.replace(u' ', u'_')))
file.write(u'endmap\n')
return
#################################################################################################
def write_thcoords(file, cavename = u'cave', coordinates = None, coordsyst = None, icomments = True, thlang = u'en'):
"""
Function to write the file Legends/entrances_coordinates.th
INPUTS:
file : variable that sets the file.th
cavename : name of the cave
cordinates : Coordinates of the Cave
coordsyst : Coordinates system and projection
icomments : True if comments in the file
False if not
thlang : 'fr' for french
'en' for english
... other languages not implemented
OUTPUTS:
None
USAGE:
write_thcoords(file, cavename, coordinates, coordsyst, icomments, thlang)
Author: Xavier Robert, Grenoble 2021/01/03
"""
# Coordinates definition
if coordinates:
if coordsyst:
# Transform Lambert coordinates into Lat Long coordinates
inProj = Proj(coordsyst)
outProj = Proj('epsg:4326')
latc, longc = transform(inProj, outProj, float(coordinates[0]), float(coordinates[1]))
else:
latc = coordinates[1] + u'(Check coord. syst.)'
longc = coordinates[0] + u'(Check coord. syst.)'
altc = coordinates[2]
else:
latc = u'None'
longc = u'None'
altc = u'None'
file.write(u'encoding utf-8 \n\n')
if icomments:
if thlang == u'fr':
file.write(u'# Copyright (C) %s Xavier Robert <xavier.robert***@***ird.fr>\n' %(str(datetime.datetime.now().year)))
file.write(u'# Ce travail est sous la licence Creative Commons Attribution-ShareAlike-NonCommecial :\n')
file.write(u'# <http://creativecommons.org/licenses/by-nc-sa/4.0/>\n\n')
elif thlang == u'en':
file.write(u'# Copyright (C) %s Xavier Robert <xavier.robert***@***ird.fr>\n' %(str(datetime.datetime.now().year)))
file.write(u'# This work is under the Creative Commons Attribution-ShareAlike-NonCommecial License:\n')
file.write(u'# <http://creativecommons.org/licenses/by-nc-sa/4.0/>\n\n')
file.write(u'layout Entrances_coords_%s\n\n' %(cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr':
file.write(u'\t# Layout qui définit les différentes variables contenant du texte avec \n')
file.write(u"\t# les coordonnées de l'entrée que nous voulons ajouter au header.\n")
file.write(u"\t# Nous avons besoin d'une variable par entrée.\n")
file.write(u'\t# Ce layout est appelé par le layout Coords_Header ci-dessous\n\n')
elif thlang == u'en':
file.write(u'\t# Layout where we define the different variables that contain the text with \n')
file.write(u'\t# the entrance coordinates we want to print in the header.\n')
file.write(u'\t# We need one variable per entrance.\n')
file.write(u'\t# This layout is called by the layout Coords_Header below\n\n')
file.write(u'\tcode tex-map\n')
file.write(u'\t\t\\def\\thjunk{ }\n')
file.write(u'\t\t\\def\\thlocation%s{%s -- Lat. : %s N ; Long. : %s E ; Alt. : %s m}\n' %(cavename.replace(u' ', u'_'), cavename.replace(u' ', u'_'), str(latc), str(longc), str(altc)))
# We probably need in the future to iterate on the number of entrances...
# I do not knwo for the moment if Visual Top take in account different entrences coordinates
file.write(u'\tendcode\n\n')
file.write(u'\tendlayout\n\n')
file.write(u'layout Coords_Header_%s\n\n' %(cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr': file.write(u'\t# Layout that set the presentation for the entrance coordinates.\n\n')
file.write(u'\tcopy Entrances_coords_%s\n\n' %(cavename.replace(u' ', u'_')))
if icomments:
if thlang == u'fr':
file.write(u'\t# Appelle le layout ci-dessus Entrances_coords où nous avons défini les différentes \n')
file.write(u'\t# variables qui contiennent le texte avec \n')
file.write(u'\t# les coordonnées des entrées à écrire dans le header.\n\n')
elif thlang == u'en':
file.write(u'\t# it calls the layout above Entrances_coords where we defined the different \n')
file.write(u'\t# variables that contain the text with \n')
file.write(u'\t# the entrance coordinates we want to print in the header.\n\n')
file.write(u'\tcode tex-map\n')
file.write(u'\t\t\\def\\nostring{}\n')
file.write(u'\t\t\\def\\thsizexl{}\n')
file.write(u'\t\t\\def\\thsizel{}\n')
file.write(u'\t\t\\def\\thsizem{}\n')
file.write(u'\t\t\\ifx\\thsizexl\\nostring\\def\\thsizexl{30}\\else\\fi\n')
file.write(u'\t\t\\ifx\\thsizel\\nostring\\def\\thsizel{24}\\else\\fi\n')
file.write(u'\t\t\\ifx\\thsizem\\nostring\\def\\thsizem{12}\\else\\fi\n\n')
file.write(u'\t\t\\ECoordinates={\n')
file.write(u'\t\t\t\\edef\\tmp{\\thjunk} \\ifx\\tmp\\empty \\else\n')
file.write(u'\t\t\t\t{\\size[\\thsizem] \\ss\\thjunk\\vss}\n')
file.write(u'\t\t\t\\fi\n')
file.write(u'\t\t\t\\edef\\tmp{\\thlocation%s} \\ifx\\tmp\\empty \\else\n' %(cavename.replace(u' ', u'_')))
file.write(u'\t\t\t\t# The first one should be without hskip\n')
file.write(u'\t\t\t\t{\\size[\\thsizem]\\hskip2cm \\ss\\thlocation%s\\vss}\n' %(cavename.replace(u' ', u'_')))
file.write(u'\t\t\t\\fi\n')
file.write(u'\t\t\t}\n')
file.write(u'\tendcode\n\n')
file.write(u'\tendlayout\n\n')
return
@@ -0,0 +1,131 @@
######!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Script to build Therion files
By Xavier Robert
Lima, 2016.06.21
USAGE :
1- Run in the terminal: $ python buildthconfig.py
INPUTS:
The inputs are in the script file, in the "# Define data to analysis" section.
The different arguments are described.
xavier.robert@ujf-grenoble.fr
(c) licence CCby-nc : http://creativecommons.org/licenses/by-nc/3.0/ 2015
"""
###### To DO : #######
# -
###### End To DO #######
from __future__ import division
# This to be sure that the result of the division of integers is a real, not an integer
# Import modules
import sys
import os
import copy
#from unittest import TestCase
#import funniest
#class TestJoke(TestCase):
# def test_is_string(self):
# s = funniest.joke()
# self.assertTrue(isinstance(s, basestring))
from utils.buildparam import builddictcave
from utils.buildthconfig import *
if __name__ == "__main__":
# build dictionnaries
dictcave, data = builddictcave()
thlang = data[0]
thcfile = data[1]
thcfnme = data[2]
thcpath = data[3]
thconfigfile = data[4]
thconfigpath = data[5]
thconfigfnme = data[6]
icomments = data[7]
icoupe = data[8]
Errfiles = data[9]
# check if the files exists
if thcfnme[-4:] != '.thc':
thcfnme = thcfile + '.thc'
if thcpath != None :
if thcpath[-1] != '/':
thcpath = thcpath + '/'
if not Errfiles :
checkfiles(thcpath + thcfnme)
else:
print('WARNING: I will erase previous ' + thcpath + thcfnme +' files !')
else:
if not Errfiles :
checkfiles(thcfnme)
else:
print('WARNING: I will erase previous ' + thcfnme +' files !')
if thconfigfnme[-9:] != '.thconfig':
thconfigfnme = thconfigfnme +'.thconfig'
if thconfigpath != None :
if thconfigpath[-1] != '/':
thconfigpath = thcpath + '/'
if not Errfiles:
checkfiles(thconfigpath + thconfigfnme)
else:
print('WARNING: I will erase previous ' + thconfigpath + thconfigfnme + ' files !')
else:
if not Errfiles :
checkfiles(thconfigfnme)
else:
print('WARNING: I will erase previous ' + thconfigfnme + ' files !')
# build thc file
if thcfile :
if thcpath != None :
writethc(thcpath + thcfnme)
else:
writethc(thcfnme)
# build thconfig file
if thconfigfile :
# write the file
if thconfigpath != None:
if thcpath != None:
writethconfig(thconfigpath + thconfigfnme, icomments, icoupe, thlang,
dictcave,
thcfile, thcpath + thcfnme)
else:
writethconfig(thconfigpath + thconfigfnme, icomments, icoupe, thlang,
dictcave,
thcfile, thcfnme)
else:
if thcpath != None:
writethconfig(thconfigfnme, icomments, icoupe, thlang,
dictcave,
thcfile, thcpath + thcfnme)
else:
writethconfig(thconfigfnme, icomments, icoupe, thlang,
dictcave,
thcfile, thcfnme)
# END
+501
View File
@@ -0,0 +1,501 @@
######!/usr/bin/env python
# -*- coding: utf8 -*-
# coding: utf8
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
# Modifié Alex 2025 07 01
"""
!---------------------------------------------------------!
! !
! Tro to Therion !
! !
! Code to transform the .tro files !
! Visual Topo into files that can !
! be used by Therion !
! !
! Written by Xavier Robert !
! !
!---------------------------------------------------------!
ENGLISH :
This code is to transform the .tro file from Visualtopo (http://vtopo.free.fr/)
into files that can be read by Therion (http://therion.speleo.sk/).
It reads .tro file and produce one .th file (file with survey data),
and one thconfig file (file that is used to compile and build the survey with Therion).
TODOS : - Correct the errors in encodings... This is the most important....
- Check all the situations possibles...
- Add title to the centerline !
"""
# Do divisions with Reals, not with integers
# Must be at the beginning of the file
from __future__ import division
#from __future__ import unicode_literals
import sys, os, wget, logging
from urllib.error import HTTPError
# Import Python modules
#modulesNames = ['sys', 'warnings']
#for module in modulesNames:
# try:
# # because we want to import using a variable, do it this way
# module_obj = __import__(module)
# # create a global object containging our module
# globals()[module] = module_obj
# except ImportError:
# sys.exit("ERROR : Module " + module + " not present. \n\n Please, install it \
# \n\n Edit the source code for more information")
from .buildparam import *
from .vtopotools import *
from .datathwritetools import *
from .buildthconfig import *
from Lib.general_fonctions import Colors
import Lib.global_data as global_data
log = logging.getLogger("Logger")
#################################################################################################
def tro2th(fle_tro_fnme = None, fle_th_fnme = None,
fle_tro_encoding=None,
thlang = u'fr',
cavename = None,
icomments = True, icoupe = True,
ithconfig = True, istructure = True, thconfigfnme = None,
ithc = True, thcpath = None, thcfnme = u'config.thc',
sourcefile = None, xviscale = 1000, xvigrid = 10, scale = 500,
Errorfiles = True):
"""
Main function to convert tro to th files.
This is this function that should be called from python.
INPUTS:
fle_tro_fnme : (string) Path and name of the .tro file to convert.
if None (value by default), the function does not convert anything
but build .thconfig and config.thc files
If the path is not given, the function will look in the folder from where it is launched
fle_th_fnme : (string) Path and name of the .th file to create from the .tro file.
If None (value by default), this file is created from the .tro file name
and in the same folder than that .tro file
thlang : (string) String that set the language. 'fr' by default.
If you need english, change 'fr' to 'en' in the function definition
set 'fr' for french
set 'en' for english
... other languages are not implemented
cavename : (string) Name of the cave.
If set to None (default value), it is get from the .tro file.
icomments : (Boolean) To add (True, by default) or not (False) comments in the produced files
icoupe : (Boolean) To set (True, by default) or not (False) an extended-elevation layout in the .thconfig file
ithconfig : (Boolean) To set if the thconfig file is created (True, by default) or not
istructure : (Boolean) To set if the structure and the addditional files are created (True, by default) or not
thconfigfnme : (string) Path and name of the thconfig file.
If None (by default), path and name build from the .tro file
ithc : (Boolean) To build (True, by default) or not (False) a config file config.thc
thcpath : (string) Path to the directry that contains the config file called in the cave.thconfig file.
If used with ithc = False, this path is only used for the declaration
in the cave.thconfig
If used with ithc = True, the config file will be written in that directory.
Set to None by default
thcfnme : (string) Name of the config.thc (value by default if set to None or if ommitted)
sourcefile : (list of strings) Define the source files declared in the cave.thconfig
ex :['example.th', 'example.th2', 'example-coupe.th2']
If None or ommitted, it is build from the .tro file or the cavename
xviscale : (Real) Scale of the xvi file.
Set to 1000 by default that corresponds to 1/1000
xvigrid : (Real) Spacing of the grid for the xvi, in meters.
Set 10 by default
scale : (Real) scale of the map
Set to 500 by default that corresponds to 1/500
Errorfiles : (Boolean) If True (by default), an error will be raised if output files exists in the folder
If False, only a warning is raised, and the previous files are erased by the new ones.
Use with caution
OUTPUTS:
Depending of the parameters inputed, several files can be produced
cavename.th : survey data for Therion
cavename.thconfig : file to build the pdf's maps and others
confgi.thc : config file for the .thconfig file.
USAGE:
To build everything
tro2th(fle_tro_fnme = 'Test', fle_th_fnme = 'Test',
thlang = 'fr',
cavename = 'Test',
icomments = True, icoupe = True,
ithconfig = True, thconfigfnme = None,
ithc = True, thcpath = None, thcfnme = 'config.thc',
sourcefiles = None, xviscale = 1000, xvigrid = 10, scale = 500,
Errorfiles = True)
To build only a .th file
tro2th(fle_tro_fnme = 'Test', fle_th_fnme = 'Test',
thlang = 'fr',
cavename = 'Test',
icomments = True, icoupe = True,
ithconfig = False
ithc = False
Errorfiles = True)
To build only a thonfig file, in english, without any comments and without extended elevation layout
tro2th(thlang = 'en',
cavename = 'Test',
icomments = False, icoupe = False,
ithconfig = False, thconfigfnme = None,
ithc = False, thcpath = my/path/to/my/confg/file, thcfnme = 'config.thc',
sourcefiles = ['Test.th', 'Test.th2'], xviscale = 1000, xvigrid = 10, scale = 500,
Errorfiles = True)
Author: Xavier Robert, Lima 2016/06/27
Licence: CCby-nc
"""
if thlang in [u'fr', u'FR', u'Fr', u'fR']: thlang = u'fr'
elif thlang in [u'en',u'EN', u'En', u'eN']: thlang = u'en'
else: raise NameError(u'ERROR: Language %s not implemented\n'
u' Use "en" instead' % thlang )
print(u'____________________________________________________________\n\n\t\tTRO 2 THERION\n____________________________________________________________\n')
if thlang == u'fr':
print(u'\nEcrit par Xavier Robert, Groupe spéléo Vulcain - Lyon, France\n')
elif thlang == u'en':
print(u'\nWritten by Xavier Robert, Groupe spéléo Vulcain - Lyon, France\n')
print(u'____________________________________________________________\n\n')
coordsyst = None
coordinates = None
if fle_tro_fnme is not None:
if fle_tro_fnme[-4:] != u'.tro':
fle_tro_fnme = fle_tro_fnme + u'.tro'
# check if file exists
if os.path.isfile(fle_tro_fnme) == False :
if thlang == u'fr': raise NameError(u'ERROR : Le fichier {FileNa} n\'existe pas'.format(FileNa=str(fle_tro_fnme)))
elif thlang == u'en': raise NameError(u'ERROR : File {FileNa} does not exist'.format(FileNa=str(fle_tro_fnme)))
if fle_th_fnme is None:
# convert tro file to th file
print('1')
cavename, coordinates, coordsyst, fle_th_fnme = convert_tro(fle_tro_fnme, fle_tro_encoding=fle_tro_encoding,
icomments = icomments, icoupe = icoupe, istructure = istructure,
thlang = thlang, Errorfiles = Errorfiles)
else:
print(2)
cavename, coordinates, coordsyst, fle_th_fnme = convert_tro(fle_tro_fnme, fle_th_fnme, cavename,
icomments = icomments, icoupe = icoupe, istructure = istructure,
thlang = thlang, Errorfiles = Errorfiles)
if thlang == u'fr': print(u'\tFichier Therion %s construit à partir des données %s' %(fle_th_fnme, fle_tro_fnme))
elif thlang == u'en': print(u'\tFile %s built from %s' %(fle_th_fnme, fle_tro_fnme))
else:
if thlang == u'fr': print(u'\tPas de fichier .tro en entrée, pas de fichier de données .th créé...')
elif thlang == u'en': print(u'\tNo .tro File input, no .th data file created...')
# Build here the new structure:
if istructure: build_structure(u'cave', Errorfiles = True)
if sourcefile is None:
if fle_th_fnme is None:
if cavename is None: cavename = u'cave'
sourcefile = [cavename.replace(u' ', u'_') + u'.th',
u'#' + cavename.replace(u' ', u'_') + u'.th2',
u'#' + cavename.replace(u' ', u'_') + u'-coupe.th2']
else:
sourcefile = [fle_th_fnme, u'#' + fle_th_fnme[0:-4] + u'th2', u'#' + fle_th_fnme[0:-4] + u'-coupe.th2' ]
# Build the dictionnary for the thconfig file
dictcave = [sourcefile, xviscale, xvigrid, cavename, coordsyst, scale]
# build thc file
if ithc :
if thcpath is not None :
# Download the config file from my github page
try:
wget.download('https://raw.githubusercontent.com/robertxa/Th-Config-Xav/master/config.thc',
thcpath)
#thcpath + thcfnme)
except HTTPError:
if thcpath[-1] not in ['/', '\\']: thcpath = thcpath + '/'
writethc(thcpath + thcfnme, istructure)
except FileNotFoundError:
if thcpath[-1] not in ['/', '\\']: thcpath = thcpath + '/'
writethc(thcpath + thcfnme, istructure)
else:
# Download the config file from my github page
try:
if istructure: wget.download('https://raw.githubusercontent.com/robertxa/Th-Config-Xav/master/config.thc',
cavename.replace(u' ', u'_') + '/')
else: wget.download('https://raw.githubusercontent.com/robertxa/Th-Config-Xav/master/config.thc')
except HTTPError:
writethc(thcfnme, cavename, istructure)
except FileNotFoundError:
writethc(thcfnme, cavename, istructure)
# build thconfig file
# Needs to be change to take in account istructure
if ithconfig :
# write the file
if thconfigfnme is None or thconfigfnme == u'' or thconfigfnme == u' ':
if fle_th_fnme is None: thconfigfnme = cavename.replace(u' ', u'_') + u'.thconfig'
else: thconfigfnme = fle_th_fnme[0:-3] + u'.thconfig'
if thcpath is not None:
thcfnme = thcpath + thcfnme
writethconfig(cavename.replace(u' ', u'_') + thconfigfnme, icomments, icoupe, thlang,
dictcave,
ithc, thcfnme)
else:
thcfnme = thcfnme
writethconfig(cavename.replace(u' ', u'_') + thconfigfnme, icomments, icoupe, thlang,
dictcave,
ithc, cavename.replace(u' ', u'_') + u'/config.thc')
if istructure:
# build cavename-tot.th file
f3w = open(cavename.replace(u' ', u'_') + '/' + cavename.replace(u' ', u'_') + '-tot.th', 'w')
write_thtot(f3w, cavename, icomments, thlang)
f3w.closed
print(u'\tFile ' + cavename.replace(u' ', u'_') + u'/' + cavename.replace(u' ', u'_') + u'-tot.th written...\n')
# build cavename-maps.th file
f4w = open(cavename.replace(u' ', u'_') + u'/' + cavename.replace(u' ', u'_') + '-maps.th', 'w')
write_thmaps(f4w, cavename, icomments, thlang)
f4w.closed
print(u'\tFile ' + cavename.replace(u' ', u'_') + u'/' + cavename.replace(u' ', u'_') + u'-maps.th written...\n\n')
# build Legends/entrances-coordinates.th file
f5w = open(cavename.replace(u' ', u'_') + '/Legends/entrances_coordinates.th', 'w')
write_thcoords(f5w, cavename, coordinates, coordsyst, icomments, thlang)
f5w.closed
print(u'\tFile ' + cavename.replace(u' ', u'_') + u'/Legends/entrances_coordinates.th written...\n\n')
print(u'____________________________________________________________')
print(u'')
return
#################################################################################################
def build_structure(cavename, Errorfiles = True):
"""
Check and build if needed the new structure:
-Cave/
-Data/
-cavename.th
(-cavename.th2)
-Legends/
-entrances_coordinates.th
-Outputs/
-outputs.txt
-Cavename.thconfig
-cavename-tot.th
-cavename-maps.th
-config.thc
INPUTS:
cavename = name of the cave that is used to build all the folders and file structure
Errorfiles = Boolean; If True (Default), the program stops if the structure already exists
If False or none, if the structure exists, it is erased
OUTPUTS:
None, except a new structure
USAGE:
build_structure(cavename, Errorfiles)
"""
# check if the folder cavename/ exists
if os.path.exists(cavename.replace(u' ', u'_')):
if Errorfiles:
# Stop
raise NameError(u'ERROR : Folder {FileNa} does exist'.format(FileNa=str(cavename.replace(u' ', u'_'))))
else:
print(u'WARNING: I have erased folder %s' % cavename.replace(u' ', u'_'))
if not os.path.exists(cavename.replace(u' ', u'_') + u'/Data'): os.mkdir(cavename.replace(u' ', u'_') + u'/Data')
if not os.path.exists(cavename.replace(u' ', u'_') + u'/Legends'): os.mkdir(cavename.replace(u' ', u'_') + u'/Legends')
if not os.path.exists(cavename.replace(u' ', u'_') + u'/Outputs'):
os.mkdir(cavename.replace(u' ', u'_') + u'/Outputs')
# Add outputs.txt file
mkfle_output_txt(cavename.replace(u' ', u'_'))
# - if no, create it and create the other files
else:
# Create the subfolders
os.mkdir(cavename.replace(u' ', u'_'))
os.mkdir(cavename.replace(u' ', u'_') + u'/Data')
os.mkdir(cavename.replace(u' ', u'_') + u'/Outputs')
# Add outputs.txt file
mkfle_output_txt(cavename.replace(u' ', u'_'))
os.mkdir(cavename.replace(u' ', u'_') + u'/Legends')
return
#################################################################################################
def mkfle_output_txt(cavename):
"""
Build the file Output.txt in the folder cavename/Outputs/
INPUTS:
cavename = name of the cave
OUTPUTS:
None
USAGE:
create_output_txt(cavename)
"""
# Open the cavename/Outputs/outputs.txt file
f1w = open(cavename.replace(u' ', u'_') + u'/Outputs/outputs.txt','w')
f1w.write(u'Folder where Therion outputs are exported \n\n')
# close the cavename/Outputs/outputs.txt file
f1w.closed
print(u'\tFile ' + cavename.replace(u' ', u'_') + u'/Outputs/outputs.txt written...')
return
#################################################################################################
def convert_tro(fle_tro_fnme, fle_tro_encoding=None, fle_th_fnme = None, cavename = None,
icomments = True, icoupe = True, istructure = True, thlang = u'fr', Errorfiles = True):
"""
Function that manages the tro 2 th conversion
INPUTS:
fle_tro_fnme : path and file name of the .tro file to convert
fle_th_fnme : path and file name of the .th file to create.
If ommitted, set to None, and this varaible will be set in function of the fle_tro_fnme or cavename
cavename : Name of the cave. If ommitted, it is set to None, and it is get from the .tro file
icomments : (Boolean) To add (True, by default) or not (False) comments in the produced files
icoupe : (Boolean) To set (True, by default) or not (False) an extended-elevation layout in the .thconfig file
istructure : (Boolean) To set if the structure and the addditional files are created (True, by default) or not
thlang : (string) String that set the language. 'fr' by default.
If you need english, change 'fr' to 'en' in the function definition
set 'fr' for french
set 'en' for english
Errorfiles : True (by default if ommitted) to get an error if the .th file already exists.
False if only a warning...
OUTPUTS:
new .th file with surveyed data for Therion
cavename : Name of the cave from the .tro file
coordinates : Coordinates of the entrance
coordsyst : Coordinates system used by the .tro file
USAGE:
cavename, coordsyst = convert_tro(fle_tro_fnme, [fle_th_fnme = fle_th_fnme, cavename = cavename, Errorfiles = Errorfiles])
fle_th_fnme, cavename and Errorfiles can be ommitted.
Author: Xavier Robert, Lima 2016/06/27
Licence: CCby-nc
"""
#from codecs import open
# Initialization of some variables...
#xcoord=0.
#ycoord=0.
#alt=0.
# open the .tro survey
if thlang == u'fr': log.info(f"Travail sur le fichier VisualTopo: {Colors.ENDC}{fle_tro_fnme}")
elif thlang == u'en':log.info(f"Processing VisualTopo file: {Colors.ENDC}{fle_tro_fnme}")
# print(' ')
fle_tro = open(fle_tro_fnme, 'r', encoding=fle_tro_encoding)
# read the .tro file
try:
lines = fle_tro.readlines()
# change the encoding
lines = convert_text(lines)
except UnicodeDecodeError:
# find the line where there is the error
# initiate the line number
lineNumber = 1
try:
# read the first line
line = fle_tro.redline()
while line:
# update the line number
lineNumber += 1
# read the next line
line = fle_tro.readline()
except UnicodeDecodeError:
log.error(f"Special or accentuated character not supporter line {Colors.ENDC}{lineNumber}{Colors.ERROR}, correct the input file")
global_data.error_count += 1
# read the header
coordinates = None
cavename, coordinates, coordsyst, club, entrance, versionfle = read_vtopo_header(lines)
if cavename is None or cavename == '' or cavename == ' ':
cavename = u'cave'
if fle_th_fnme is None:
fle_th_fnme = cavename.replace(u' ', u'_') + u'.th'
print (fle_th_fnme)
if fle_th_fnme[-3:] != u'.th':
fle_th_fnme = fle_th_fnme + u'.th'
# Build here the new structure:
if istructure: build_structure(cavename, Errorfiles)
# check if file exists...
checkfiles(fle_th_fnme, Errorfiles)
# open the .th file
if istructure: fle_th = open (cavename.replace(u' ', u'_') + '/Data/' + fle_th_fnme, 'w')
else: fle_th = open (fle_th_fnme, 'w')
# write the .th header
writeheader_th(fle_th, cavename, entrance)
# initiate variables
i = 0
iline = []
dataold = []
# get line numbers of the lines beginning with 'Param'
for line in lines:
if u'Param' in line: iline.append(i)
i+=1
for j in iline:
# read the settings of the survey
settings, comments = read_settings(lines[j].replace(u'\n', u''))
# read the data from the tro file
data = read_data(lines, settings, j, iline)
# write centerline header
writecenterlineheader(fle_th, entrance, settings, comments, data, coordsyst, coordinates, club,
icomments, thlang)
# write the data to the .th file
writedata(fle_th, settings, data, dataold)
# write the end of the centerline in the .th file
fle_th.write(u'\n\tendcenterline\n\n')
dataold = data
# write the end of the survey in the .th file
fle_th.write(u'\nendsurvey\n')
fle_th.close
#print (fle_th_fnme)
if thlang == u'fr': log.info(f"Fichier Therion {Colors.ENDC}{fle_th_fnme}{Colors.INFO} écrit !")
elif thlang == u'en': log.info(f"Therion file {Colors.ENDC}{fle_th_fnme}{Colors.INFO} written!")
return cavename, coordinates, coordsyst, fle_th_fnme
#################################################################################################
if __name__ == u'__main__':
# initiate variables
# run the transformation
tro2th()
@@ -0,0 +1,304 @@
######!/usr/bin/env python
# -*- coding: utf-8 -*-
# coding: utf8
# Copyright (c) 2020 Xavier Robert <xavier.robert@ird.fr>
# SPDX-License-Identifier: GPL-3.0-or-later
# Modifié Alex 2025 07 01
"""
Functions to work on vtopo data to be able to write them in the Therion format
By Xavier Robert
Lima, 2016.06.21
USAGE :
- They are normally used by other scripts
INPUTS:
The inputs are in the script file, in the "# Define data to analysis" section.
The different arguments are described.
"""
###### To DO : #######
# - Take in account the 'I' (extended elevation) inverse option in vtopo file --> set extend right/left
###### End To DO #######
from __future__ import division
# This to be sure that the result of the division of integers is a real, not an integer
#from __future__ import unicode_literals
# Import modules
import sys, os
############################################################################
def read_vtopo_header(lines):
"""
Function to read header from vtopofile
INPUTS:
lines: file .tro read by the fonction lines = readlines(file_vtopo)
OUTPUTS (all are strings):
cavename : Name of the cave
coordinates : Entrance coordinates
coordsyst : Coordinates system to set the entrance coordinates
club : Name of the group that explored the cave
entrance : Entrance of the cave
versionfle : Vtopo version that has been used to produce the vtopofile
USAGE:
cavename, coordinates, coordsyst, club, entrance, versionfle = read_vtopo_header(lines)
Author: Xavier Robert, Lima 2016/06/27
Licence: CCby-nc
"""
# coord_dict: French Lambert system. To find number of your system, see extern/proj4/nad/epsg
# file in the therion source distribution. You can add your own lines/systems
# [Note alex: ajout des systèmes compatibles VTopo]
coord_dict = {
u'SWISS' : u'EPSG:21780',
u'LT72' : u'EPSG:31300',
u'LT93' : u'EPSG:2154',
u'LT1' : u'EPSG:27571',
u'LT2' : u'EPSG:27572',
u'LT2E' : u'EPSG:27572',
u'LT3' : u'EPSG:27573',
u'LT4' : u'EPSG:27574',
u'UTM30' : u'EPSG:32630',
u'UTM31' : u'EPSG:32631',
u'UTM32' : u'EPSG:32632',
u'UTM42' : u'EPSG:32642',
u'UTM30E' : u'EPSG:23030',
u'UTM31E' : u'EPSG:23031',
u'UTM32E' : u'EPSG:23032'
}
cavename = ''
club = ''
coordtro = ''
coordinates = ["0.0", "0.0", "0.0"]
for line in lines:
if u"Version" in line:
versionfle = line[1].replace(u'\n', u'').rstrip(u'\n\r').split(' ')
if u'Trou' in line:
# read Trou
(cavename, xcoord, ycoord, alt, coordtro) = line[5:].replace(u'\n', u'').rstrip(u'\n\r').split(u',')
coordinates = [xcoord, ycoord, alt]
# read club
if u'Club' in line: club = line[5:].replace(u'\n', u'')
# read entrance name
if u'Entree' in line : entrance = line[7:].replace(u'\n', u'')
if coordtro in coord_dict:
# Rewrite the coordinate system to be read by Therion
# French Lambert system. To find number of your system, see extern/proj4/nad/epsg file in the therion source distribution. You can add you own lines/systems
coordsyst = coord_dict[coordtro]
else:
coordsyst = None
return cavename, coordinates, coordsyst, club, entrance, versionfle
############################################################################
def read_settings(line):
"""
Function to read the line that define the settings of the survey session :
intruments, directions, units, calibrations,...
INPUTS:
line : string extractd from the .tro file that contains the information on the survey session
OUTPUTS:
settings : list of strings with all the measurments settings
comments : string that correspond to the end of the string "Line"
that do not correspond to the settings
USAGE:
settings, comments = read_settings(line)
Author: Xavier Robert, Lima 2016/06/27
Licence: CCby-nc
"""
# Question: Do we have to update the code in function of the vtopo version number?
param = line[6:].rstrip(u'\n\r').split(u' ')
k = 9
#k = 6
if 'Topof' in param[:k]:
k = k + 1
if 'Prof' in param[:k] or 'Deniv' in param[:k]:
k = k - 1
# Transformation de l'avant-dernier champ s'il correspond à une date jj/mm/aaaa
if '/' in param[k-1] :
try:
jj, mm, aaaa = param[k-1].split('/')
param[k-1] = f"{aaaa} {mm} {jj}"
except ValueError:
pass # ne rien faire si la date est mal formée
settings = param[:k]
#commentst = param[k+2:]
commentst = param[k:]
comments = " ".join(str(elem) for elem in commentst)
#ucomments=comments.decode('us-ascii', errors = 'replace')
#print ucomments
return settings, comments#.encode('utf-8', errors = "replace")
############################################################################
def read_data(lines, settings, j, iline):
"""
Function to read the data from the line
INPUTS:
lines : file .tro read by the fonction lines = readlines(file_vtopo)
settings : list of strings with all the measurments settings;
output of the function read_settings
j : number of the line that corresponds to the settings line in the list "lines"
iline : list of line numbers that correspond to the different settings line in the list "lines"
OUTPUTS:
data : list of lists of data (string format)
USAGE:
data = read_data(lines, settings, j, iline)
Author: Xavier Robert, Lima 2016/06/27
Licence: CCby-nc
"""
data = []
# check if we are at the end of the iline file or not !
if iline.index(j) < len(iline)-1:
for i in range(j+1, iline[iline.index(j)+1]):
datal = [x for x in lines[i].replace(u'\n', u'').rstrip(u'\n\r').split(u' ') if x != u'']
data.append(datal)
else:
i = j+1
while 1:
if 'Configuration' in lines[i]:
break
else:
datal = [x for x in lines[i].replace(u'\n', u'').rstrip('\n\r').split(u' ') if x != u'']
data.append(datal)
i+=1
# remove white lines in datao
data = [x for x in data if x != []]
return data
############################################################################
def convert_text(lines):
"""
Fonction to convert characters encoding...
The problem is that .tro files are encode with strange Windows settings,
and the accentuation is not well understood by other systems
Bug, that is not working well
INPUTS:
lines :
OUTPUTS:
USAGE:
lines = convert_text(lines)
Author: Xavier Robert, Lima 2016/06/27
Licence: CCby-nc
"""
dictcaract ={'\xe8' : u'è',
'\xe0' : u'à',
'\xe9' : u'é',
'\xe0' : u'à',
'\xf9' : u'ù',
'\xea' : u'ê',
'\xeb' : u'ë',
'\xf1' : u'ñ',
'\xfb' : u'û',
'\xee' : u'î',
'\xef' : u'ï'}
for line in lines:
#for line in lines.decode('cp1252'):
#line = line.decode('cp1252')
# windows = latin-1 ? cp-1252 ? cp1252 ? mbcs ?
for elem in dictcaract:
#print line
if elem in line:
line = line.replace(elem, dictcaract[elem])
return lines
############################################################################
if __name__ == u"__main__":
"""
Function to test sub-functions
"""
from datathwritetools import writeheader_th, writecenterlineheader, writedata
fle_tro_fnme = u'Test.tro'
fle_th_fnme = u'test.th'
icomments = True
thlang = u'fr'
cavename = u'cave'
# open tro file
fle_tro = open(fle_tro_fnme, u'rU')
# open new th file
fle_th = open(cavename.replace(u' ', u'_') + '/Data/' + fle_th_fnme, u'w')
# read the tro file
lines = fle_tro.readlines()
lines = convert_text(lines)
# read the header
#cavename, coordinates, coordtro, club, entrance = read_vtopo_header(fle_tro)
cavename, coordinates, coordsyst, club, entrance, versionfle = read_vtopo_header(lines)
writeheader_th(fle_th, cavename, entrance)
# read line to line and find the Param
i = 0
iline = []
dataold = []
# get line numbers of the lines beginning with 'Param'
for line in lines:
#print i
#print i, line.replace('\n', '')
if u'Param' in line: iline.append(i)
i+=1
for j in iline:
# read the settings of the survey
settings, comments = read_settings(lines[j].replace(u'\n', u''))
data = read_data(lines, settings, j, iline)
# write centerline header
writecenterlineheader(fle_th, entrance, settings, comments, data, coordsyst, coordinates, club,
icomments, thlang)
# write the data to the .th file
writedata(fle_th, settings, data, dataold)
fle_th.write(u'\n\tendcenterline\n')
dataold = data
fle_th.write(u'\nendsurvey\n')
fle_tro.close
fle_th.close