Source code for IMTreatment.utils.units

# -*- coding: utf-8 -*-
#!/bin/env python3

# Copyright (C) 2003-2007 Gaby Launay

# Author: Gaby Launay  <gaby.launay@tutanota.com>
# URL: https://framagit.org/gabylaunay/IMTreatment
# Version: 1.0

# This file is part of IMTreatment.

# IMTreatment is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.

# IMTreatment is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import numpy as np
import re
import unum
import unum.units as units
try:
    units.counts = unum.Unum.unit('counts')
    units.px = unum.Unum.unit('px')
except:
    pass
from ..utils.types import ARRAYTYPES, INTEGERTYPES, NUMBERTYPES, STRINGTYPES


[docs]def make_unit(string): """ Function helping for the creation of units. For more details, see the Unum module documentation. Parameters ---------- string : string String representing some units. Returns ------- unit : unum.Unum object unum object representing the given units Examples -------- >>> make_unit("m/s") 1 [m/s] >>> make_unit("N/m/s**3") 1 [kg/s4] """ if string == "": return unum.Unum({}) # Safe check forbidden = ['import', '=', '\n', ';', ':', '"', "'", "open"] forbidden += [key for key in globals().keys()] for f in forbidden: if f in string: raise Exception("Unauthorized string: {}".format(f)) if re.match("[a-zA-Z]+\(.*\)", string): raise Exception("No call allowed here") # Replace '^' by '**' string = string.replace('^', '**') # exec env = {} exec("from unum.units import *;res = {}".format(string), env) return env['res']
[docs]def make_unit_old(string): """ Function helping for the creation of units. For more details, see the Unum module documentation. Parameters ---------- string : string String representing some units. Returns ------- unit : unum.Unum object unum object representing the given units Examples -------- >>> make_unit("m/s") 1 [m/s] >>> make_unit("N/m/s**3") 1 [kg/s4] """ if len(string) == 0: return unum.Unum({}) brackets = ['(', ')', '[', ']'] symbambig = {"**": "^"} operators = ['*', '^', '/'] toremove = [' '] def spliting(string): """ Split the given string to elemental brick. """ # suppression symboles inutiles for symb in toremove: string = string.replace(symb, '') # remplacement symboles ambigues for key in symbambig: string = string.replace(key, symbambig[key]) # découpage de la chaine de caractère pieces = [string] for symb in operators + brackets: j = len(pieces)-1 while True: if (pieces[j].find(symb) != -1 and len(pieces[j]) != len(symb)): splitpiece = list(pieces[j].partition(symb)) pieces[j:j+1] = splitpiece j += 2 else: j -= 1 if j < 0: break # Suppression des caractères nuls for j in np.arange(len(pieces)-1, -1, -1): if pieces[j] == '': pieces[j:j+1] = [] # Add power where needed for i, piece in enumerate(pieces): match = re.match('([a-zA-Z]+)([0-9]+)', piece) if match is not None: pieces[i:i+1] = [match.groups()[0], "^", match.groups()[1]] return pieces def app_brackets(strlist): """ Apply all the brackets. """ level = 0 levels = [] for i in np.arange(len(strlist)): if strlist[i] in ['(', '[']: level += 1 elif strlist[i-1] in [')', ']'] and i-1 > 0: level -= 1 if level < 0: raise ValueError("I think you have a problem" " with your brackets, dude") levels.append(level) # boucle sur les parenthèses while True: if len(strlist) == 1: return app_one_bracket(strlist) first_ind = levels.index(np.max(levels)) last_ind = None for i in np.arange(first_ind, len(levels)): if levels[i] < levels[first_ind]: last_ind = i-1 break if last_ind is None: last_ind = len(levels) - 1 if np.all(np.array(levels) == 0): result = app_one_bracket(strlist) return result else: strlist[first_ind:last_ind+1] \ = [app_one_bracket(strlist[first_ind+1:last_ind])] levels[first_ind:last_ind+1] = [np.max(levels)-1] def app_one_bracket(stringlist): """ Apply one bracket. """ stringlist = list(stringlist) # traitement des nombres for j in np.arange(len(stringlist)-1, -1, -1): try: stringlist[j] = float(stringlist[j]) if stringlist[j] % 1 == 0: stringlist[j] = int(stringlist[j]) except: pass # traitement des unités for j in np.arange(len(stringlist)-1, -1, -1): if not isinstance(stringlist[j], (unum.Unum, NUMBERTYPES)): if not stringlist[j] in operators + brackets: if not stringlist[j] in unum.Unum.getUnitTable(): raise ValueError("I don't know this unit : '{}'," "little bird. (or maybe it's an " "operator i'm missing...)." .format(stringlist[j])) stringlist[j] = unum.Unum({stringlist[j]: 1}) # traitement des opérateurs liste = stringlist # ^ for ind in np.arange(len(liste)-1, 0, -1): if isinstance(liste[ind], unum.Unum): continue if liste[ind] == '^': liste[ind - 1:ind + 2] = [liste[ind - 1]**liste[ind + 1]] ind -= 2 if ind < 0: break # / for ind in np.arange(len(liste)-1, 0, -1): if isinstance(liste[ind], unum.Unum): continue if liste[ind] == '/': liste[0:1] = [liste[0]/liste[ind + 1]] liste[ind:ind+2] = [] #liste[ind - 1:ind + 2] = [liste[ind - 1]/liste[ind + 1]] ind -= 2 if ind < 0: break # * for ind in np.arange(len(liste)-1, 0, -1): if isinstance(liste[ind], unum.Unum): continue if liste[ind] == '*': liste[ind - 1:ind + 2] = [liste[ind - 1]*liste[ind + 1]] ind -= 2 if ind < 0: break return liste[0] strlist = spliting(string) unity = app_brackets(strlist) return unity