propagateErrorLN.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import numpy
  2. import convolveLN
  3. def generateSample(mu,cv):
  4. return numpy.array([convolveLN.ln(mu,cv) for i in range(10000)])
  5. def getEdges(a):
  6. #convert array of bin centers a to array of bin edges with one more element than a
  7. a1=numpy.zeros(len(a)+1)
  8. a2=numpy.zeros(a1.shape)
  9. a1[1:]=a
  10. a2[:-1]=a
  11. e=0.5*(a1+a2)
  12. e[0]=2*e[1]-e[2]
  13. e[-1]=2*e[-2]-e[-3]
  14. return e
  15. def calculateDistribution(fy,muTarget,mu,cv,dydp):
  16. #calculate distribution of random variable y with a functional dependence
  17. #on random parameters p, each with a log-normal
  18. #distribution with a mean mu(p) and coefficients of variation cv(p)
  19. #and dydp giving partial derivatives of y on p
  20. #muTarget is the target mean of y distribution
  21. #fy is the set of values y where distribution is evaluated at
  22. #Parameters mu, cv and dydp are given as vectors/lists
  23. qa=mu*dydp
  24. A=numpy.sum(qa)
  25. qa*=muTarget/A
  26. cvPrime=cv*A/muTarget
  27. sigmaS=numpy.sqrt(numpy.log(1+cvPrime*cvPrime))
  28. sign=qa>=0
  29. muS=numpy.zeros(qa.shape)
  30. muS[sign]=numpy.log(qa[sign]/numpy.sqrt(1+cvPrime[sign]*cvPrime[sign]))
  31. muS[~sign]=numpy.log(-qa[~sign]/numpy.sqrt(1+cvPrime[~sign]*cvPrime[~sign]))
  32. y=convolveLN.convolveLN(fy,sigmaS,muS,sign)
  33. return y/numpy.sum(y)
  34. def generateDistribution(fx,muTarget,mu,cv,dydp, dbg=0):
  35. #sum randomly generated variables to approximate distribution of
  36. #variable y with a functional dependence y(p) on random parameters p,
  37. #each with a log-normal (LN) distribution
  38. #with a mean mu(p) and coefficient of variation cv(p)
  39. #target mean of y is muTarget
  40. #distribution is evaluated at points fy,
  41. #dydp are derivatives of y with respect to parameters p
  42. qa=mu*dydp
  43. A=numpy.sum(qa)
  44. qa*=muTarget/A
  45. cvPrime=cv*A/muTarget
  46. samples=[a*generateSample(1,c) for a,c in zip(qa,cvPrime)]
  47. mean=[numpy.mean(s) for s in samples]
  48. std=[numpy.std(s) for s in samples]
  49. convSample=numpy.zeros(len(samples[0]))
  50. msg='[{}] mean={:.2f} std={:.2f} cv={:.2f}'
  51. for i in range(len(cv)):
  52. convSample+=samples[i]
  53. if dbg:
  54. print(msg.format(i,mean[i],std[i],std[i]/mean[i]))
  55. convM=numpy.mean(convSample)
  56. convS=numpy.std(convSample)
  57. if dbg:
  58. code=x
  59. print(msg.format(code,convM,convS,convS/convM))
  60. h,be=numpy.histogram(convSample,bins=getEdges(fx))
  61. #h should be len(fx)
  62. return h/numpy.sum(h)