Source code for openalea.rose.mockup.rose_time

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# $Id$
#

import re


[docs] def bySegments(x, Xmin, Xmax, Ymin, Ymax): # cloud be placed somewhere else, but used only here, so it remains here. """computes a value for a function defined by segments : Xmin, Xmax, Ymin, Ymax. Pre-conditions : - Xmin < Xmax Post conditions: - x < Xmin : return Ymin - x > Xmax : return Ymax - else : - K= (Ymax-Ymin) / (Xmax - Xmin) - return Ymin + K * (x-Xmin) :param x: the x value :param Xmin: the low value of the x range :param Xmax: the high value of the x range :param Ymin: the low value of the y range :param Ymax: the high value of the y range :return: the interpolated y value """ if (Xmax <= Xmin) or (Ymin == Ymax): raise ValueError if x <= Xmin: return Ymin elif x >= Xmax: return Ymax K = (Ymax - Ymin) / float(Xmax - Xmin) return Ymin + K * (x - Xmin)
[docs] def invBySegments(y, Xmin, Xmax, Ymin, Ymax): # cloud be placed somewhere else, but used only here, so it remains here. """computes the reverse function of bySegments : preconditions : Ymin != Ymax :param y: the y value :param Xmin: the low value of the x range :param Xmax: the high value of the x range :param Ymin: the low value of the y range :param Ymax: the high value of the y range :return: the interpolated x value :warning: we only process positive slopes. """ if Ymin == Ymax: raise ValueError if y < Ymin: return Xmin elif y > Ymax: return Xmax K = (Xmax - Xmin) / float(Ymax - Ymin) return Xmin + K * (y - Ymin)
[docs] def checkIfIn(left, right, value): # cloud be placed somewhere else, but used only here, so it remains here. """ Ensure that "value" meets the following conditions : - if left <= right : - value will be inside [left - right] - else : - value will be outside ]right - left[ :param left: a limit that is allowed to be lower than "value" :param right: a limit that is allowed to be higher than "value" :param value: the value to be checked :return: either "value" if it passes the test, or left, or right, depending on whether is closest to "value" :note: the result is assigned a forced value when calling checkIfIn (guard,guard, value) """ if left <= right: # we want to include if value < left: value = left elif value > right: value = right else: # we want to exclude if ( value < (left + right) / 2.0 ): # is value lower than the mean of the interval ? if value > right: # is value inside the interval ? value = right # if so : value is set to the lower border elif value < left: # else : is value inside the interval ? value = left # if so : value is set to the higher border return value
########################## P A Y L O A D # duration of the states (empiric data) AngleMin = 0 SepalExtAngleMax = 120 SepalExtTimeMin = 0.0 SepalExtTimeMax = 0.1 SepalIntAngleMax = 110 SepalIntTimeMin = 0.0 SepalIntTimeMax = 0.3 PetalExtAngleMax = 90 PetalExtTimeMin = 0.2 PetalExtTimeMax = 0.9 PetalIntAngleMax = 80 PetalIntTimeMin = 0.4 PetalIntTimeMax = 0.9 # beginning of SR - start plageCPV = invBySegments( SepalExtAngleMax * 0.8, SepalExtTimeMin, SepalExtTimeMax, AngleMin, SepalExtAngleMax ) # Inside Petal angle that marks the beginning of FO AnglePetaleIntDebutFO = 20 finSR = invBySegments( AnglePetaleIntDebutFO, PetalIntTimeMin, PetalIntTimeMax, AngleMin, PetalIntAngleMax ) # duration of SR plageSR = finSR - plageCPV # plageSR=0.4 # remaining time plageFO = 1 - finSR # =0.52
[docs] def computeStage(stade, avancement): tauxAvancement = avancement / 100.0 # back to decimal value # re.search ("(?i)...) : case insensitive search if re.search("(?i)bfv", stade): return 0 # ( [0,0,0,0],[10]) # bud not opened yet elif re.search("(?i)cpv", stade): time01 = plageCPV * tauxAvancement # sepals are opening elif re.search("(?i)sr", stade): time01 = plageCPV + plageSR * tauxAvancement # petals not yet opening elif re.search("(?i)fo", stade): time01 = plageCPV + plageSR + plageFO * tauxAvancement # petals opening elif re.search("(?i)ff", stade): time01 = 1 # or 1.00 ? print("time01=%f" % time01) return time01
# parameters # # S+ S- P+ P- # X min 0 0 2 4 # Xmax 1 3 4 9 # Ymin 0 0 0 0 # Ymax 120 110 90 80
[docs] def outerSepalAngle(time01): return bySegments(time01, 0, 0.1, 0, 120)
[docs] def invertOuterSepalAngle(angle): return invBySegments(angle, 0, 0.1, 0, 120)
[docs] def innerSepalAngle(time01): return bySegments(time01, 0, 0.3, 0, 110)
[docs] def invertInnerSepalAngle(angle): return invBySegments(angle, 0, 0.3, 0, 110)
[docs] def outerPetalAngle(time01): return bySegments(time01, 0.2, 0.9, 0, 90) # paramètres vus avec Jess
[docs] def invertOuterPetalAngle(angle): return invBySegments(angle, 0.2, 0.9, 0, 90)
[docs] def innerPetalAngle(time01): return bySegments(time01, 0.4, 0.9, 0, 80) # // vus avec Jess
[docs] def notation2flowerAngles(stade, avancement=0.0, sepalAngles=None, flowerAngles=None): """translate observations to flower time01 @param stade : a state of flower devlt in [BVF, CPV, SR, FO, FF] @param avancement : step in the current stade (0 .. 100) percent @param sepalAngles : parameters to draw sepals if they have been caught up in the MTG : [length of sepal, angle/vertical] @param flowerAngles : parameters to draw sepals if they have been caught up in the MTG : [length of petal, angle/vertical] TODO : separer angles et dimensions """ if sepalAngles is None: sepalAngles = [] if flowerAngles is None: flowerAngles = [] # TODO : déterminer une priorité des entrées pour éviter # les incohérences tq pétales + ouverts que sépales flowerHeight = 20 petalExtAngle = None petalIntAngle = 0 if flowerAngles is not None: if len(flowerAngles) > 0: flowerHeight = flowerAngles[0] # length mm if len(flowerAngles) > 1: petalExtAngle = flowerAngles[1] # angle degrees if len(flowerAngles) > 2: petalExtAngle = flowerAngles[2] # angle degrees sepalLength = flowerHeight # TODO : petal length sepalExtAngle = None if sepalAngles is not None: if len(sepalAngles) > 0: sepalLength = sepalAngles[0] # length mm if len(sepalAngles) > 1: sepalExtAngle = sepalAngles[1] # angle degrees if len(sepalAngles) > 2: sepalExtAngle = sepalAngles[2] # angle degrees avancement = checkIfIn(0.0, 100.0, avancement) # avancement must inside [0,100] time01 = computeStage(stade, avancement) if re.search("(?i)bfv", stade): return [], [] elif re.search("(?i)(cpv)|(sr)|(fo)", stade): # |fo to check continuity sepalExtAngle = outerSepalAngle(time01) sepalIntAngle = innerSepalAngle(time01) petalExtAngle = outerPetalAngle(time01) petalIntAngle = innerPetalAngle(time01) return [sepalLength, [sepalExtAngle, sepalIntAngle]], [ flowerHeight, [petalExtAngle, petalIntAngle], ] elif re.search("(?i)ff", stade): return [], [0, [120, 120]] if sepalExtAngle is None: # no measure for sepal angles, so # we compute them both sepalExtAngle = outerSepalAngle(time01) sepalIntAngle = innerSepalAngle(time01) else: sepalIntAngle = sepalExtAngle * 0.8 # better idea : # this is the mean angle ; so : # -> compute it # then compute the ext and int angles such as e.g +- 10-20% petalFacts = [flowerHeight, [petalExtAngle, petalIntAngle]] sepalFacts = [] if sepalLength is not None: sepalFacts.append(sepalLength) sepalFacts.append([sepalExtAngle, sepalIntAngle]) # return outputs return sepalFacts, petalFacts
[docs] def test(): minX = 1 maxX = 10 minY = 12 maxY = 14 factor = 100 if minX < maxX: thisX = minX thatX = maxX else: thisX = maxX thatX = minX # direct for x in range(int(thisX * factor), int(thatX * factor)): y = x / float(factor) print("%f %f" % (y, bySegments(y, minX, maxX, minY, maxY))) # inverse for x in range(int(maxY * factor), int(minY * factor), -1): y = x / float(factor) print("%f %f" % (y, invBySegments(y, minX, maxX, minY, maxY))) # reciprocity for x in range(int(thisX * factor), int(thatX * factor)): y = x / float(factor) print( "%f %f" % ( y, invBySegments( bySegments(y, minX, maxX, minY, maxY), minX, maxX, minY, maxY ), ) )
# e.g. inside gnuplot (plot "< bySegments.py" w l) if __name__ == "__main__": test()