def _makeMapObjects(self): if self.map is None: self.map = InterpolatingFunction( (self.x_axis, self.y_axis, self.z_axis), self.data, 0.) self.map_gx = self.map.derivative(0) self.map_gy = self.map.derivative(1) self.map_gz = self.map.derivative(2)
def smooth_function_from_coordinates( x, y, # coordinates of some curve sample_fraction=1.0, # fraction of x,y points used for resampling spline_smoothing=4, # degree of spline (1 gives piecewise linear) ): """ Given a set of coordinates in the `x` and `y` arrays, create a smooth function from these coordinates by 1) resampling n uniformly distributed points by linear interpolation of the `x` and `y` coordinates, where n is given by `sample_fraction` times the length of `x`; and 2) interpolating the resampled points by a smooth spline, where `spline_smoothing` is an integer holding the degree of the piecewise polynomial pieces of the spline (0 and 1 gives a piecewise linear function, 2 and higher gives splines of that order). Return the smooth function as a Python function of x, together with the (uniformly distributed) resampled points on which the smooth function is based. """ # Construct linear interpolator of data points from Scientific.Functions.Interpolation \ import InterpolatingFunction linear = InterpolatingFunction([x], y) # Resample xp = np.linspace(x[0], x[-1], sample_fraction * len(x)) yp = np.array([linear(xi) for xi in xp]) # Spline smoothing or linear interpolation, based on (xp,yp) if spline_smoothing >= 2: from scipy.interpolate import UnivariateSpline as Spline function = Spline(xp, yp, s=0, k=spline_smoothing) else: function = InterpolatingFunction([xp], yp) return function, xp, yp
def findAlphaBeta(self): if self.res_shells is None: return p = self.model_amplitudes*self.exp_amplitudes/self.epsilon t = None alpha = [] beta = [] for rsc, rsa in self.res_shells: a = b = c = d = 0. tw = len(rsc) + 2.*len(rsa) for ri in rsc: a += self.model_amplitudes[ri]**2/self.epsilon[ri] b += self.exp_amplitudes[ri]**2/self.epsilon[ri] c += p[ri] d += p[ri]*p[ri] for ri in rsa: a += 2.*self.model_amplitudes[ri]**2/self.epsilon[ri] b += 2.*self.exp_amplitudes[ri]**2/self.epsilon[ri] c += 2.*p[ri] d += 2.*p[ri]*p[ri] a /= tw b /= tw c /= tw d /= tw if d < a*b: t = 0. else: def g(t): return N.sqrt(1.+4.*a*b*t*t)-2.*t*_l(t, p, rsc, rsa)-1. if t is None: t = 1. while g(t) > 0.: t = t/2. t1 = t while g(t) < 0.: t = 2.*t t2 = t g1 = g(t1) g2 = g(t2) while t2-t1 > 1.e-3*t1: t = t1-g1*(t2-t1)/(g2-g1) gt = g(t) if gt == 0.: break elif gt < 0: t1 = t g1 = gt else: t2 = t g2 = gt s = N.sqrt(1.+4.*a*b*t*t) v = N.sqrt((s-1)/(2*a)) u = N.sqrt((s+1)/(2*b)) alpha.append(v/u) beta.append(1./(u*u)) self.alpha = InterpolatingFunction((self.ssq_av_shell,), N.array([alpha[0]]+alpha+[alpha[-1]])) self.beta = InterpolatingFunction((self.ssq_av_shell,), N.array([beta[0]]+beta+[beta[-1]]))
def Integrate(xdata,ydata): x_array=Numeric.array(xdata) y_array=Numeric.array(ydata) # Create the interpolating function f = InterpolatingFunction((x_array,), y_array) f_integral=f.definiteIntegral() return f_integral
def correlation(self, nsteps): """Return the autocorrelation function of the process (as estimated from the AR model) up to |nsteps| times the sampling interval. """ poles = self.poles() cpoles = N.conjugate(poles) x = 0. exponents = N.arange(self.order - 1, nsteps + self.order - 1) for i in range(len(poles)): pole = poles[i] factor = N.multiply.reduce((pole-poles)[:i]) * \ N.multiply.reduce((pole-poles)[i+1:]) * \ N.multiply.reduce((pole-1./cpoles)) try: x = x + pole**exponents / factor except OverflowError: # happens with some Python versions on some systems power = N.zeros(exponents.shape, N.Complex) for i in range(len(exponents)): try: power[i] = pole**exponents[i] except ValueError: pass x = x + power / factor cf = -self.sigsq * x / N.conjugate(self.coeff[0]) if not isComplex(self.coeff): cf = realPart(cf) return InterpolatingFunction((self.delta_t * N.arange(nsteps), ), cf)
def staticStructureFactor(self, q_range=(1., 15.), subset=None, weights=None, random_vectors=15, first_mode=6): """ :param q_range: the range of angular wavenumber values :type q_range: tuple :param subset: the subset of the universe used in the calculation (default: the whole universe) :type subset: :class:~MMTK.Collections.GroupOfAtoms :param weights: the weight to be given to each atom in the average (default: coherent scattering lengths) :type weights: :class:~MMTK.ParticleProperties.ParticleScalar :param random_vectors: the number of random direction vectors used in the orientational average :type random_vectors: int :param first_mode: the first mode to be taken into account for the fluctuation calculation. The default value of 6 is right for molecules in vacuum. :type first_mode: int :returns: the Static Structure Factor as a function of angular wavenumber :rtype: Scientific.Functions.Interpolation.InterpolatingFunction """ if subset is None: subset = self.universe if weights is None: weights = self.universe.getParticleScalar('b_coherent') mask = subset.booleanMask() weights = N.repeat(weights.array, mask.array) weights = weights / N.sqrt(N.add.reduce(weights * weights)) friction = N.repeat(self.friction.array, mask.array) r = N.repeat(self.universe.configuration().array, mask.array) first, last, step = (q_range + (None, ))[:3] if step is None: step = (last - first) / 50. q = N.arange(first, last, step) kT = Units.k_B * self.temperature natoms = subset.numberOfAtoms() sq = 0. random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: sab = N.zeros((natoms, natoms), N.Float) for i in range(first_mode, self.nmodes): irt = self.rawMode(i).inv_relaxation_time d = N.repeat((self.rawMode(i)*v).array, mask.array) \ / N.sqrt(friction) sab = sab + (d[N.NewAxis, :] - d[:, N.NewAxis])**2 / irt sab = sab[N.NewAxis, :, :] * q[:, N.NewAxis, N.NewAxis]**2 phase = N.exp(-1.j*q[:, N.NewAxis] * N.dot(r, v.array)[N.NewAxis, :]) \ * weights[N.NewAxis, :] temp = N.sum(phase[:, :, N.NewAxis] * N.exp(-0.5 * kT * sab), 1) temp = N.sum(N.conjugate(phase) * temp, 1) sq = sq + temp.real return InterpolatingFunction((q, ), sq / len(random_vectors))
def EISF(self, q_range=(0., 15.), subset=None, weights=None, random_vectors=15, first_mode=6): if subset is None: subset = self.universe if weights is None: weights = self.universe.getParticleScalar('b_incoherent') weights = weights * weights weights = weights * subset.booleanMask() total = weights.sumOverParticles() weights = weights / total first, last, step = (q_range + (None, ))[:3] if step is None: step = (last - first) / 50. q = N.arange(first, last, step) f = ParticleProperties.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) f = f + (1. / mode.inv_relaxation_time) * mode.dyadicProduct(mode) f = Units.k_B * self.temperature * f / self.friction eisf = N.zeros(q.shape, N.Float) random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: for a in subset.atomList(): exp = N.exp(-v * (f[a] * v)) N.add(eisf, weights[a] * exp**(q * q), eisf) return InterpolatingFunction((q, ), eisf / len(random_vectors))
def __init__(self, data): self.data = data # (x,y,f) data for an f(x,y) function from Scientific.Functions.Interpolation \ import InterpolatingFunction # from ScientificPython self.interpolating_function = \ InterpolatingFunction(self.data[:-1], self.data[-1]) self.ndims = len(self.data[:-1]) # no of spatial dim.
def correlation(self, nsteps): """ @param nsteps: the number of time steps for which the autocorrelation function is to be evaluated @type nsteps: C{int} @returns: the autocorrelation function of the process as estimated from the AR model @rtype: L{Scientific.Functions.Interpolation.InterpolatingFunction} """ poles = self.poles() cpoles = N.conjugate(poles) x = 0. exponents = N.arange(self.order - 1, nsteps + self.order - 1) for i in range(len(poles)): pole = poles[i] factor = N.multiply.reduce((pole-poles)[:i]) * \ N.multiply.reduce((pole-poles)[i+1:]) * \ N.multiply.reduce((pole-1./cpoles)) try: x = x + pole**exponents / factor except OverflowError: # happens with some Python versions on some systems power = N.zeros(exponents.shape, N.Complex) for i in range(len(exponents)): try: power[i] = pole**exponents[i] except ValueError: pass x = x + power / factor cf = -self.sigsq * x / N.conjugate(self.coeff[0]) if not _isComplex(self.coeff): cf = _realPart(cf) return InterpolatingFunction((self.delta_t * N.arange(nsteps), ), cf)
def meanSquareDisplacement(self, subset=None, weights=None, time_range=(0., None, None), first_mode=6): """Returns the averaged mean-square displacement of the atoms in |subset| (default: all atoms) at time points defined by |time_range| using |weights| in the average (default: masses). |time_range| is a three element tuple (first, last, step). The defaults are first=0., last= three times the longest relaxation time, and step defined such that 300 points are used in total. """ if subset is None: subset = self.universe if weights is None: weights = self.universe.masses() weights = weights * subset.booleanMask() total = weights.sumOverParticles() weights = weights / (total * self.friction) first, last, step = (time_range + (None, None))[:3] if last is None: last = 3. / self.rawMode(first_mode).inv_relaxation_time if step is None: step = (last - first) / 300. time = N.arange(first, last, step) msd = N.zeros(time.shape, N.Float) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) rt = mode.inv_relaxation_time d = (weights * (mode * mode)).sumOverParticles() N.add(msd, d * (1. - N.exp(-rt * time)) / rt, msd) N.multiply(msd, 2. * Units.k_B * self.temperature, msd) return InterpolatingFunction((time, ), msd)
def spectrum(self, omega): """Return the frequency spectrum of the process at the angular frequencies |omega| (an array). """ sum = 1. for i in range(1, len(self.coeff) + 1): sum = sum - self.coeff[-i] * N.exp(-1j * i * self.delta_t * omega) s = 0.5 * self.delta_t * self.sigsq / (sum * N.conjugate(sum)).real return InterpolatingFunction((omega, ), s)
def memoryFunction(self, nsteps): """Return the memory function corresponding to the autocorrelation function of the process up to |nsteps| times the sampling interval. """ mz = self.memoryFunctionZapprox(nsteps + self.order) mem = mz.divide(nsteps - 1)[0].coeff[::-1] if len(mem) == nsteps + 1: mem = mem[1:] mem[0] = 2. * realPart(mem[0]) time = self.delta_t * N.arange(nsteps) return InterpolatingFunction((time, ), mem)
def EISF(self, q_range=(0., 15.), subset=None, weights=None, random_vectors=15, first_mode=6): """ :param q_range: the range of angular wavenumber values :type q_range: tuple :param subset: the subset of the universe used in the calculation (default: the whole universe) :type subset: :class:~MMTK.Collections.GroupOfAtoms :param weights: the weight to be given to each atom in the average (default: incoherent scattering lengths) :type weights: :class:~MMTK.ParticleProperties.ParticleScalar :param random_vectors: the number of random direction vectors used in the orientational average :type random_vectors: int :param first_mode: the first mode to be taken into account for the fluctuation calculation. The default value of 6 is right for molecules in vacuum. :type first_mode: int :returns: the Elastic Incoherent Structure Factor (EISF) as a function of angular wavenumber :rtype: Scientific.Functions.Interpolation.InterpolatingFunction """ if subset is None: subset = self.universe if weights is None: weights = self.universe.getParticleScalar('b_incoherent') weights = weights * weights weights = weights * subset.booleanMask() total = weights.sumOverParticles() weights = weights / total first, last, step = (q_range + (None, ))[:3] if step is None: step = (last - first) / 50. q = N.arange(first, last, step) f = ParticleProperties.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) f = f + (1. / mode.inv_relaxation_time) * mode.dyadicProduct(mode) f = Units.k_B * self.temperature * f / self.friction eisf = N.zeros(q.shape, N.Float) random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: for a in subset.atomList(): exp = N.exp(-v * (f[a] * v)) N.add(eisf, weights[a] * exp**(q * q), eisf) return InterpolatingFunction((q, ), eisf / len(random_vectors))
def spectrum(self, omega): """ @param omega: the angular frequencies at which the spectrum is to be evaluated @type omega: C{Numeric.array} of C{float} @returns: the frequency spectrum of the process @rtype: C{Numeric.array} of C{float} """ sum = 1. for i in range(1, len(self.coeff) + 1): sum = sum - self.coeff[-i] * N.exp(-1j * i * self.delta_t * omega) s = 0.5 * self.delta_t * self.sigsq / (sum * N.conjugate(sum)).real return InterpolatingFunction((omega, ), s)
def memoryFunction(self, nsteps): mz = self.memoryFunctionZ() mem = mz.divide(nsteps - 1)[0].coeff[:] mem.reverse() if len(mem) == nsteps + 1: mem = mem[1:] if isComplex(self.coeff[0]): mem = N.array([complex(m.real, m.imag) for m in mem]) else: mem = N.array([float(m) for m in mem]) mem[0] = 2. * realPart(mem[0]) time = self.delta_t * N.arange(nsteps) return InterpolatingFunction((time, ), mem)
def meanSquareDisplacement(self, subset=None, weights=None, time_range=(0., None, None), first_mode=6): """ :param subset: the subset of the universe used in the calculation (default: the whole universe) :type subset: :class:~MMTK.Collections.GroupOfAtoms :param weights: the weight to be given to each atom in the average (default: atomic masses) :type weights: :class:~MMTK.ParticleProperties.ParticleScalar :param time_range: the time values at which the mean-square displacement is evaluated, specified as a range tuple (first, last, step). The defaults are first=0, last= 20 times the longest vibration perdiod, and step defined such that 300 points are used in total. :type time_range: tuple :param first_mode: the first mode to be taken into account for the fluctuation calculation. The default value of 6 is right for molecules in vacuum. :type first_mode: int :returns: the averaged mean-square displacement of the atoms in subset as a function of time :rtype: Scientific.Functions.Interpolation.InterpolatingFunction """ if subset is None: subset = self.universe if weights is None: weights = self.universe.masses() weights = weights * subset.booleanMask() total = weights.sumOverParticles() weights = weights / (total * self.friction) first, last, step = (time_range + (None, None))[:3] if last is None: last = 3. / self.rawMode(first_mode).inv_relaxation_time if step is None: step = (last - first) / 300. time = N.arange(first, last, step) msd = N.zeros(time.shape, N.Float) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) rt = mode.inv_relaxation_time d = (weights * (mode * mode)).sumOverParticles() N.add(msd, d * (1. - N.exp(-rt * time)) / rt, msd) N.multiply(msd, 2. * Units.k_B * self.temperature, msd) return InterpolatingFunction((time, ), msd)
def memoryFunction(self, nsteps): """ @param nsteps: the number of time steps for which the memory function is to be evaluated @type nsteps: C{int} @returns: the memory function of the process as estimated from the AR model @rtype: L{Scientific.Functions.Interpolation.InterpolatingFunction} """ mz = self.memoryFunctionZapprox(nsteps + self.order) mem = mz.divide(nsteps - 1)[0].coeff[::-1] if len(mem) == nsteps + 1: mem = mem[1:] mem[0] = 2. * _realPart(mem[0]) time = self.delta_t * N.arange(nsteps) return InterpolatingFunction((time, ), mem)
def coherentScatteringFunction(self, q, time_range=(0., None, None), subset=None, weights=None, random_vectors=15, first_mode=6): if subset is None: subset = self.universe if weights is None: weights = self.universe.getParticleScalar('b_coherent') mask = subset.booleanMask() weights = N.repeat(weights.array, mask.array) weights = weights / N.sqrt(N.add.reduce(weights * weights)) friction = N.repeat(self.friction.array, mask.array) r = N.repeat(self.universe.configuration().array, mask.array) first, last, step = (time_range + (None, None))[:3] if last is None: last = 3. / self.rawMode(first_mode).inv_relaxation_time if step is None: step = (last - first) / 300. time = N.arange(first, last, step) natoms = subset.numberOfAtoms() kT = Units.k_B * self.temperature fcoh = N.zeros((len(time), ), N.Complex) random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: phase = N.exp(-1.j * q * N.dot(r, v.array)) for ai in range(natoms): fbt = N.zeros((natoms, len(time)), N.Float) for i in range(first_mode, self.nmodes): irt = self.rawMode(i).inv_relaxation_time d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \ / N.sqrt(friction) ft = N.exp(-irt * time) / irt N.add(fbt, d[ai] * d[:, N.NewAxis] * ft[N.NewAxis, :], fbt) N.add(fbt, (-0.5 / irt) * (d[ai]**2 + d[:, N.NewAxis]**2), fbt) N.add( fcoh, weights[ai] * phase[ai] * N.dot(weights * N.conjugate(phase), N.exp(kT * fbt)), fcoh) return InterpolatingFunction((time, ), fcoh.real / len(random_vectors))
def incoherentScatteringFunction(self, q, time_range=(0., None, None), subset=None, random_vectors=15, first_mode=6): if subset is None: subset = self.universe mask = subset.booleanMask() weights_inc = self.universe.getParticleScalar('b_incoherent') weights_inc = N.repeat(weights_inc.array**2, mask.array) weights_inc = weights_inc / N.add.reduce(weights_inc) friction = N.repeat(self.friction.array, mask.array) mass = N.repeat(self.universe.masses().array, mask.array) r = N.repeat(self.universe.configuration().array, mask.array) first, last, step = (time_range + (None, None))[:3] if last is None: last = 3. / self.weighedMode(first_mode).inv_relaxation_time if step is None: step = (last - first) / 300. time = N.arange(first, last, step) natoms = subset.numberOfAtoms() kT = Units.k_B * self.temperature finc = N.zeros((len(time), ), N.Float) eisf = 0. random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: phase = N.exp(-1.j * q * N.dot(r, v.array)) faat = N.zeros((natoms, len(time)), N.Float) eisf_sum = N.zeros((natoms, ), N.Float) for i in range(first_mode, self.nmodes): irt = self.rawMode(i).inv_relaxation_time d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \ / N.sqrt(friction) ft = (N.exp(-irt * time) - 1.) / irt N.add(faat, d[:, N.NewAxis]**2 * ft[N.NewAxis, :], faat) N.add(eisf_sum, -d**2 / irt, eisf_sum) N.add(finc, N.sum(weights_inc[:, N.NewAxis] * N.exp(kT * faat), 0), finc) eisf = eisf + N.sum(weights_inc * N.exp(kT * eisf_sum)) return InterpolatingFunction((time, ), finc / len(random_vectors))
def staticStructureFactor(self, q_range=(1., 15.), subset=None, weights=None, random_vectors=15, first_mode=6): if subset is None: subset = self.universe if weights is None: weights = self.universe.getParticleScalar('b_coherent') mask = subset.booleanMask() weights = N.repeat(weights.array, mask.array) weights = weights / N.sqrt(N.add.reduce(weights * weights)) friction = N.repeat(self.friction.array, mask.array) r = N.repeat(self.universe.configuration().array, mask.array) first, last, step = (q_range + (None, ))[:3] if step is None: step = (last - first) / 50. q = N.arange(first, last, step) kT = Units.k_B * self.temperature natoms = subset.numberOfAtoms() sq = 0. random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: sab = N.zeros((natoms, natoms), N.Float) for i in range(first_mode, self.nmodes): irt = self.rawMode(i).inv_relaxation_time d = N.repeat((self.rawMode(i)*v).array, mask.array) \ / N.sqrt(friction) sab = sab + (d[N.NewAxis, :] - d[:, N.NewAxis])**2 / irt sab = sab[N.NewAxis, :, :] * q[:, N.NewAxis, N.NewAxis]**2 phase = N.exp(-1.j*q[:, N.NewAxis] * N.dot(r, v.array)[N.NewAxis, :]) \ * weights[N.NewAxis, :] temp = N.sum(phase[:, :, N.NewAxis] * N.exp(-0.5 * kT * sab), 1) temp = N.sum(N.conjugate(phase) * temp, 1) sq = sq + temp.real return InterpolatingFunction((q, ), sq / len(random_vectors))
from Gnuplot import plot from RandomArray import random dt = 1. t = dt * N.arange(500) if 1: data = N.sin(t) + N.cos(3. * t) + 0.1 * (random(len(t)) - 0.5) data = data + 0.1j * (random(len(t)) - 0.5) if 0: data = [0.] for i in range(500 + len(t) - 1): data.append(mean(data[-500:]) + gaussian(0., 0.1)) data = N.exp(1j * N.array(data[500:])) if 0: #data = readArray('~/scientific/Test/data') string = open('/users1/hinsen/scientific/Test/data').read()[4:] data = N.array(eval(string)) data = data[:, 0] model = AutoRegressiveModel(20, data, dt) print model.coeff print model.poles() c = model.correlation(200) cref = InterpolatingFunction((t, ), AutoCorrelationFunction(data))[:200] m = model.memoryFunction(200) s = model.spectrum(N.arange(0., 5., 0.01)) #plot(c.real, cref.real); plot(c.imag, cref.imag) print model.frictionConstant(), model.memoryFunctionZ()( 1.), m.definiteIntegral() #plot(m.real, m.imag) plot(m)
x = D(10, index=0, order=2) y = D(0, index=1, order=2) z = D(1, index=2, order=2) r = somefunc(x, y, z) print r # (40, [3, -1, 20], [[0, 0, 0], [0, 0, 0], [0, 0, 20]]) print "d^2(somefunc)/dzdx:", r[2][2][0] # 0 print "d^2(somefunc)/dz^2:", r[2][2][2] # 20 print "\n\ntesting interpolation:" from Scientific.Functions.Interpolation \ import InterpolatingFunction as Ip t = sequence(0, 10, 0.1) v = sin(t) vi = Ip((t, ), v) # interpolate and compare with exact result: print "interpolated:", vi(5.05), " exact:", sin(5.05) # interpolate the derivative of v: vid = vi.derivative() print "interpolated derivative:", vid(5.05), " exact:", cos(5.05) # compute the integral of v over all t values: print "definite integral:", vi.definiteIntegral(), \ " exact:", -cos(t[-1]) - (-cos(t[0])) # add path to Grid2D: sys.path.insert(0, os.path.join(os.environ['scripting'], 'src', 'py', 'examples')) from Grid2D import Grid2D g = Grid2D(dx=0.1, dy=0.2) f = g('sin(pi*x)*sin(pi*y)')
class EventDamageModel: """ Object for working out the damage and cost """ STRUCT_LOSS_TITLE = "STRUCT_LOSS_$" #"Structure Loss ($)" CONTENTS_LOSS_TITLE = "CONTENTS_LOSS_$" #"Contents Loss ($)" CONTENTS_DAMAGE_TITLE = "CONTENTS_DAMAGE_fraction" #"Contents damaged (fraction)" STRUCT_DAMAGE_TITLE = "STRUCT_DAMAGE_fraction" #"Structure damaged (fraction)" COLLAPSE_CSV_INFO_TITLE = "COLLAPSE_CSV_INFO" #"Calculation notes" MAX_DEPTH_TITLE = "MAX_DEPTH_m" #"Inundation height above ground floor (m)" STRUCT_COLLAPSED_TITLE = "STRUCT_COLLAPSED" #"collapsed structure if 1" STRUCT_INUNDATED_TITLE = "STRUCT_INUNDATED" #"inundated structure if 1" double_brick_damage_array = num.array( [ #[-kinds.default_float_kind.MAX, 0.0], [-1000.0, 0.0], [0.0 - depth_epsilon, 0.0], [0.0, 0.016], [0.1, 0.150], [0.3, 0.425], [0.5, 0.449], [1.0, 0.572], [1.5, 0.582], [2.0, 0.587], [2.5, 0.647], [1000.0, 64.7] #[kinds.default_float_kind.MAX,64.7] ]) if scipy_available: double_brick_damage_curve = interp1d(double_brick_damage_array[:, 0], double_brick_damage_array[:, 1]) else: double_brick_damage_curve = InterpolatingFunction( \ (num.ravel(double_brick_damage_array[:,0:1]),), num.ravel(double_brick_damage_array[:,1:])) brick_veeer_damage_array = num.array( [ #[-kinds.default_float_kind.MAX, 0.0], [-1000.0, 0.0], [0.0 - depth_epsilon, 0.0], [0.0, 0.016], [0.1, 0.169], [0.3, 0.445], [0.5, 0.472], [1.0, 0.618], [1.5, 0.629], [2.0, 0.633], [2.5, 0.694], [1000.0, 69.4] #[kinds.default_float_kind.MAX,69.4] ]) if scipy_available: brick_veeer_damage_curve = interp1d(brick_veeer_damage_array[:, 0], brick_veeer_damage_array[:, 1]) else: brick_veeer_damage_curve = InterpolatingFunction( \ (num.ravel(brick_veeer_damage_array[:,0:1]),), num.ravel(brick_veeer_damage_array[:,1:])) struct_damage_curve = { 'Double Brick': double_brick_damage_curve, 'Brick Veneer': brick_veeer_damage_curve } default_struct_damage_curve = brick_veeer_damage_curve contents_damage_array = num.array([ #[-kinds.default_float_kind.MAX, 0.0], [-1000.0, 0.0], [0.0 - depth_epsilon, 0.0], [0.0, 0.013], [0.1, 0.102], [0.3, 0.381], [0.5, 0.500], [1.0, 0.970], [1.5, 0.976], [2.0, 0.986], [1000.0, 98.6] #[kinds.default_float_kind.MAX,98.6] ]) if scipy_available: contents_damage_curve = interp1d(contents_damage_array[:, 0], contents_damage_array[:, 1]) else: contents_damage_curve = InterpolatingFunction( \ (num.ravel(contents_damage_array[:,0:1]),), num.ravel(contents_damage_array[:,1:])) #building collapse probability # inundation depth above ground floor, m depth_upper_limits = [ depth_epsilon, 1.0, 2.0, 3.0, 5.0, kinds.default_float_kind.MAX ] # shore mistance, m shore_upper_limits = [125, 200, 250, kinds.default_float_kind.MAX] # Building collapse probability collapse_probability = [ [0.0, 0.0, 0.0, 0.0], #Code below assumes 0.0 [0.05, 0.02, 0.01, 0.0], [0.6, 0.3, 0.1, 0.05], [0.8, 0.4, 0.25, 0.15], [0.95, 0.7, 0.5, 0.3], [0.99, 0.9, 0.65, 0.45] ] def __init__(self, max_depths, shore_distances, walls, struct_costs, content_costs): """ max depth is Inundation height above ground floor (m), so the ground floor has been taken into account. """ self.max_depths = [float(x) for x in max_depths] self.shore_distances = [float(x) for x in shore_distances] self.walls = walls self.struct_costs = [float(x) for x in struct_costs] self.content_costs = [float(x) for x in content_costs] self.structure_count = len(self.max_depths) #Fixme expand assert self.structure_count == len(self.shore_distances) assert self.structure_count == len(self.walls) assert self.structure_count == len(self.struct_costs) assert self.structure_count == len(self.content_costs) #assert self.structure_count == len(self.) def calc_damage_and_costs(self, verbose_csv=False, verbose=False): """ This is an overall method to calculate the % damage and collapsed structures and then the $ loss. """ self.calc_damage_percentages() collapse_probability = self.calc_collapse_probability() self._calc_collapse_structures(collapse_probability, verbose_csv=verbose_csv) self.calc_cost() results_dict = { self.STRUCT_LOSS_TITLE: self.struct_loss, self.STRUCT_DAMAGE_TITLE: self.struct_damage, self.CONTENTS_LOSS_TITLE: self.contents_loss, self.CONTENTS_DAMAGE_TITLE: self.contents_damage, self.MAX_DEPTH_TITLE: self.max_depths, self.STRUCT_COLLAPSED_TITLE: self.struct_collapsed, self.STRUCT_INUNDATED_TITLE: self.struct_inundated } if verbose_csv: results_dict[self.COLLAPSE_CSV_INFO_TITLE] = self.collapse_csv_info return results_dict def calc_damage_percentages(self): """ Using stage curves calc the damage to structures and contents """ # the data being created struct_damage = num.zeros(self.structure_count, num.float) contents_damage = num.zeros(self.structure_count, num.float) self.struct_inundated = [''] * self.structure_count for i, max_depth, shore_distance, wall in map( None, range(self.structure_count), self.max_depths, self.shore_distances, self.walls): ## WARNING SKIP IF DEPTH < 0.0 if 0.0 > max_depth: continue # The definition of inundated is if the max_depth is > 0.0 self.struct_inundated[i] = 1.0 #calc structural damage % damage_curve = self.struct_damage_curve.get( wall, self.default_struct_damage_curve) struct_damage[i] = damage_curve(max_depth) contents_damage[i] = self.contents_damage_curve(max_depth) self.struct_damage = struct_damage self.contents_damage = contents_damage def calc_cost(self): """ Once the damage has been calculated, determine the $ cost. """ # ensure_numeric does not cut it. self.struct_loss = self.struct_damage * \ ensure_numeric(self.struct_costs) self.contents_loss = self.contents_damage * \ ensure_numeric(self.content_costs) def calc_collapse_probability(self): """ return a dict of which structures have x probability of collapse. key is collapse probability value is list of struct indexes with key probability of collapse """ # I could've done this is the calc_damage_percentages and # Just had one loop. # But for ease of testing and bug finding I'm seperating the loops. # I'm make the outer loop for both of them the same though, # so this loop can easily be folded into the other loop. # dict of which structures have x probability of collapse. # key of collapse probability # value of list of struct indexes struct_coll_prob = {} for i, max_depth, shore_distance, wall in map( None, range(self.structure_count), self.max_depths, self.shore_distances, self.walls): # WARNING ASSUMING THE FIRST BIN OF DEPTHS GIVE A ZERO PROBABILITY depth_upper_limits = self.depth_upper_limits shore_upper_limits = self.shore_upper_limits collapse_probability = self.collapse_probability if max_depth <= depth_upper_limits[0]: continue start = 1 for i_depth, depth_limit in enumerate(depth_upper_limits[start:]): #Have to change i_depth so it indexes into the lists correctly i_depth += start if max_depth <= depth_limit: for i_shore, shore_limit in enumerate(shore_upper_limits): if shore_distance <= shore_limit: coll_prob = collapse_probability[i_depth][i_shore] if 0.0 == collapse_probability[i_depth][i_shore]: break struct_coll_prob.setdefault(coll_prob, []).append(i) break break return struct_coll_prob def _calc_collapse_structures(self, collapse_probability, verbose_csv=False): """ Given the collapse probabilities, throw the dice and collapse some houses """ self.struct_collapsed = [''] * self.structure_count if verbose_csv: self.collapse_csv_info = [''] * self.structure_count #for a given 'bin', work out how many houses will collapse for probability, house_indexes in collapse_probability.iteritems(): collapse_count = round(len(house_indexes) * probability) if verbose_csv: for i in house_indexes: # This could be sped up I think self.collapse_csv_info[i] = str(probability) + ' prob.( ' \ + str(int(collapse_count)) + ' collapsed out of ' \ + str(len(house_indexes)) + ')' for _ in range(int(collapse_count)): house_index = choice(house_indexes) self.struct_damage[house_index] = 1.0 self.contents_damage[house_index] = 1.0 house_indexes.remove(house_index) self.struct_collapsed[house_index] = 1
class DensityMap: def __init__(self, filename): if filename is None: return filetype = os.path.splitext(filename)[1] if filetype.lower() == '.ezd': self.readEZD(filename) elif filetype.lower() == '.ccp4': self.readCCP4(filename) else: raise ValueError("Unknown file type %s" % filetype) self.map = None self.box = Box( Vector(self.x_axis[0], self.y_axis[0], self.z_axis[0]), Vector(self.x_axis[-1], self.y_axis[-1], self.z_axis[-1])) self.normalize() def readEZD(filename): file = open(filename) while 1: line = file.readline() if not line: raise IOError, "unexpected end of file" words = string.split(line) if words[0] == 'MAP': break if words[0] == 'CELL': cell_x, cell_y, cell_z, alpha, beta, gamma = \ map(float, words[1:]) if alpha != 90. or beta != 90. or gamma != 90.: raise ValueError, "cell must be rectangular" if words[0] == 'EXTENT': self.nx, self.ny, self.nz = map(float, words[1:]) if words[0] == 'GRID': gnx, gny, gnz = map(float, words[1:]) data = [] while 1: line = file.readline() if not line: raise IOError, "unexpected end of file" line = string.join(string.split(line, '.-'), '. -') words = string.split(line) if words[0] == 'END': break for value in map(float, words): data.append(value) data = N.array(data) data.shape = (self.nz, self.ny, self.nx) self.data = N.transpose(data) self.x_axis = N.arange(self.nx) * (cell_x / gnx) * Units.Ang self.y_axis = N.arange(self.ny) * (cell_y / gny) * Units.Ang self.z_axis = N.arange(self.nz) * (cell_z / gnz) * Units.Ang def readCCP4(self, filename): mapfile = file(filename) header_data = mapfile.read(1024) NC, NR, NS, MODE, NCSTART, NRSTART, NSSTART, NX, NY, NZ, X, Y, Z, \ ALPHA, BETA, GAMMA, MAPC, MAPR, MAPS, AMIN, AMAX, AMEAN, \ ISPG, NSYMBT, LSKFLG = struct.unpack('=10l6f3l3f3l', header_data[:4*25]) if MODE == 2: byte_order = '=' elif MODE == 33554432: NC, NR, NS, MODE, NCSTART, NRSTART, NSSTART, NX, NY, NZ, X, Y, Z, \ ALPHA, BETA, GAMMA, MAPC, MAPR, MAPS, AMIN, AMAX, AMEAN, \ ISPG, NSYMBT, LSKFLG = struct.unpack('>10l6f3l3f3l', header_data[:4*25]) byte_order = '>' if MODE == 33554432: NC, NR, NS, MODE, NCSTART, NRSTART, NSSTART, NX, NY, NZ, \ X, Y, Z, ALPHA, BETA, GAMMA, MAPC, MAPR, MAPS, \ AMIN, AMAX, AMEAN, ISPG, NSYMBT, LSKFLG \ = struct.unpack('<10l6f3l3f3l', header_data[:4*25]) byte_order = '<' else: raise IOError("Not a mode 2 CCP4 map file") symmetry_data = mapfile.read(NSYMBT) map_data = mapfile.read(4 * NS * NR * NC) if byte_order == '=': array = N.fromstring(map_data, N.Float32, NC * NR * NS) else: array = N.zeros((NS * NR * NC, ), N.Float32) index = 0 while len(map_data) >= 4 * 10000: values = struct.unpack(byte_order + '10000f', map_data[:4 * 10000]) array[index:index + 10000] = N.array(values, N.Float32) index += 10000 map_data = map_data[4 * 10000:] values = struct.unpack(byte_order + '%df' % (len(map_data) / 4), map_data) array[index:] = N.array(values, N.Float32) del map_data array.shape = (NS, NR, NC) self.data = N.transpose(array) resolution_x = X * Units.Ang / NX resolution_y = Y * Units.Ang / NY resolution_z = Z * Units.Ang / NZ self.x_axis = (NCSTART + N.arange(NC)) * resolution_x self.y_axis = (NRSTART + N.arange(NR)) * resolution_y self.z_axis = (NSSTART + N.arange(NS)) * resolution_z def __getitem__(self, item): if not isinstance(item, tuple) or len(item) != 3: raise ValueError("indexation requires three slices") sx, sy, sz = item if not (isinstance(sx, slice) and isinstance(sy, slice) \ and isinstance(sz, slice)): raise ValueError("indexation requires three slices") new_map = DensityMap(None) new_map.data = self.data[sx, sy, sz] new_map.x_axis = self.x_axis[sx] new_map.y_axis = self.y_axis[sy] new_map.z_axis = self.z_axis[sz] new_map.map = None new_map.box = Box( Vector(new_map.x_axis[0], new_map.y_axis[0], new_map.z_axis[0]), Vector(new_map.x_axis[-1], new_map.y_axis[-1], new_map.z_axis[-1])) return new_map def normalize(self): self.data /= N.sum(N.ravel(self.data)) def makePositive(self): min = N.minimum.reduce(N.ravel(self.data)) if min < 0: nonzero_mask = self.data != 0 self.data = (self.data - min) * nonzero_mask def _makeMapObjects(self): if self.map is None: self.map = InterpolatingFunction( (self.x_axis, self.y_axis, self.z_axis), self.data, 0.) self.map_gx = self.map.derivative(0) self.map_gy = self.map.derivative(1) self.map_gz = self.map.derivative(2) def center(self): self.map = None x_center = N.sum( N.ravel(self.x_axis[:, N.NewAxis, N.NewAxis] * self.data)) y_center = N.sum( N.ravel(self.y_axis[N.NewAxis, :, N.NewAxis] * self.data)) z_center = N.sum( N.ravel(self.z_axis[N.NewAxis, N.NewAxis, :] * self.data)) self.x_axis = self.x_axis - x_center self.y_axis = self.y_axis - y_center self.z_axis = self.z_axis - z_center self.box = Box( Vector(self.x_axis[0], self.y_axis[0], self.z_axis[0]), Vector(self.x_axis[-1], self.y_axis[-1], self.z_axis[-1])) def principalAxes(self): r = self._rGrid() cm = N.sum(N.sum(N.sum(self.data[..., N.NewAxis] * r))) r = r - cm[N.NewAxis, N.NewAxis, N.NewAxis, :] nx, ny, nz = self.data.shape t = 0. for i in range(nx): # make loops explicit to conserve memory for j in range(ny): for k in range(nz): t = t + self.data[i, j, k] * r[i, j, k, N.NewAxis, :] * \ r[i, j, k, :, N.NewAxis] ev, axes = eigenvectors(t) return map(lambda a, b: (Vector(a), b), axes, ev) def principalPoints(self): (ex, vx), (ey, vy), (ez, vz) = self.principalAxes() axes = N.array([ex.array, ey.array, ez.array]) r = self._rGrid() cm = N.sum(N.sum(N.sum(self.data[..., N.NewAxis] * r))) r = r - cm[N.NewAxis, N.NewAxis, N.NewAxis, :] regions = N.greater(N.dot(r, N.transpose(axes)), 0) regions = N.sum(N.array([[[[1, 2, 4]]]]) * regions, -1) points = [] for i in range(8): mask = N.equal(regions, i) weight = N.sum(N.sum(N.sum(mask * self.data))) cmr = N.sum(N.sum(N.sum((mask*self.data)[..., N.NewAxis]*r))) \ / weight + cm points.append(Vector(cmr)) return points def overlap(self, object): self._makeMapObjects() sum = 0. for a in object.atomList(): x, y, z = a.position() sum = sum + self.map(x, y, z) return sum def gradient(self, object): self._makeMapObjects() g = ParticleVector(object.universe()) for a in object.atomList(): x, y, z = a.position() g[a] = Vector(self.map_gx(x, y, z), self.map_gy(x, y, z), self.map_gz(x, y, z)) return g def atomMap(self, object, r0=0.3): r = self._rGrid() atom_map = N.zeros(self.data.shape, N.Float) cutoff = 4. * r0 for a in object.atomList(): # An over-eager optimization: it should use # an enlarged box #if not self.box.enclosesPoint(a.position()): # continue ra = a.position().array xi1 = N.sum(self.x_axis < ra[0] - cutoff) xi2 = N.sum(self.x_axis < ra[0] + cutoff) yi1 = N.sum(self.y_axis < ra[1] - cutoff) yi2 = N.sum(self.y_axis < ra[1] + cutoff) zi1 = N.sum(self.z_axis < ra[2] - cutoff) zi2 = N.sum(self.z_axis < ra[2] + cutoff) if xi2 > xi1 and yi2 > yi1 and zi2 > zi1: dr = r[xi1:xi2, yi1:yi2, zi1:zi2] - \ ra[N.NewAxis, N.NewAxis, N.NewAxis, :] w = N.exp(-0.5 * N.sum(dr**2, axis=-1) / r0**2) lmap = atom_map[xi1:xi2, yi1:yi2, zi1:zi2] N.add(lmap, w, lmap) N.divide(atom_map, N.sum(N.sum(N.sum(atom_map))), atom_map) return atom_map def fit(self, object, r0=0.4, w_neg=1.): diff = self.atomMap(object, r0) - self.data N.multiply(diff, 1. + (w_neg - 1.) * N.less(diff, 0.), diff) return N.sum(N.sum(N.sum(diff**2))) def fitWithGradient(self, object, r0=0.4, w_neg=1.): r = self._rGrid() atom_map = N.zeros(self.data.shape, N.Float) cutoff = 4. * r0 for a in object.atomList(): ra = a.position().array xi1 = N.sum(self.x_axis < ra[0] - cutoff) xi2 = N.sum(self.x_axis < ra[0] + cutoff) yi1 = N.sum(self.y_axis < ra[1] - cutoff) yi2 = N.sum(self.y_axis < ra[1] + cutoff) zi1 = N.sum(self.z_axis < ra[2] - cutoff) zi2 = N.sum(self.z_axis < ra[2] + cutoff) if xi2 > xi1 and yi2 > yi1 and zi2 > zi1: dr = r[xi1:xi2, yi1:yi2, zi1:zi2] - \ ra[N.NewAxis, N.NewAxis, N.NewAxis, :] w = N.exp(-0.5 * N.sum(dr**2, axis=-1) / r0**2) lmap = atom_map[xi1:xi2, yi1:yi2, zi1:zi2] N.add(lmap, w, lmap) norm_factor = 1. / N.sum(N.sum(N.sum(atom_map))) N.multiply(atom_map, norm_factor, atom_map) N.subtract(atom_map, self.data, atom_map) weight = 1. + (w_neg - 1.) * N.less(atom_map, 0.) N.multiply(atom_map, weight, atom_map) g = ParticleVector(object.universe()) for a in object.atomList(): ra = a.position().array xi1 = N.sum(self.x_axis < ra[0] - cutoff) xi2 = N.sum(self.x_axis < ra[0] + cutoff) yi1 = N.sum(self.y_axis < ra[1] - cutoff) yi2 = N.sum(self.y_axis < ra[1] + cutoff) zi1 = N.sum(self.z_axis < ra[2] - cutoff) zi2 = N.sum(self.z_axis < ra[2] + cutoff) if xi2 > xi1 and yi2 > yi1 and zi2 > zi1: dr = r[xi1:xi2, yi1:yi2, zi1:zi2] - \ ra[N.NewAxis, N.NewAxis, N.NewAxis, :] lmap = atom_map[xi1:xi2, yi1:yi2, zi1:zi2] lw = weight[xi1:xi2, yi1:yi2, zi1:zi2] w = N.exp(-0.5 * N.sum(dr**2, axis=-1) / r0**2) v = N.sum( N.sum( N.sum(lmap[..., N.NewAxis] * lw[..., N.NewAxis] * dr * w[..., N.NewAxis]))) g[a] = Vector(v) return N.sum(N.sum(N.sum(atom_map**2))), -2 * norm_factor * g / r0**2 def _rGrid(self): x = N.add.outer(N.add.outer(self.x_axis, 0 * self.y_axis), 0 * self.z_axis)[..., N.NewAxis] y = N.add.outer(N.add.outer(0 * self.x_axis, self.y_axis), 0 * self.z_axis)[..., N.NewAxis] z = N.add.outer(N.add.outer(0 * self.x_axis, 0 * self.y_axis), self.z_axis)[..., N.NewAxis] return N.concatenate((x, y, z), axis=-1) def clipBelow(self, cutoff): mask = self.clipMask(cutoff) self.data *= mask self.data /= N.add.reduce(N.ravel(self.data)) self.map = None def clipAbove(self, cutoff): mask = self.clipMask(cutoff) self.data *= (1 - mask) self.data /= N.add.reduce(N.ravel(self.data)) self.map = None def clipMask(self, cutoff): max_value = N.maximum.reduce(N.ravel(self.data)) mask = N.greater_equal(self.data, cutoff * max_value) gradient_masks = [] for i in range(len(mask.shape)): upper_index = i * index_expression[::] + index_expression[1::] lower_index = i * index_expression[::] + index_expression[:-1:] gmask1 = N.greater(self.data[upper_index], self.data[lower_index]) gmask2 = N.greater(self.data[lower_index], self.data[upper_index]) gradient_masks.append((gmask1, gmask2)) while 1: new_mask = 0 * mask for i in range(len(mask.shape)): upper_index = i * index_expression[::] + index_expression[1::] lower_index = i * index_expression[::] + index_expression[:-1:] upper_mask, lower_mask = gradient_masks[i] N.logical_or(new_mask[upper_index], N.logical_and(mask[lower_index], lower_mask), new_mask[upper_index]) N.logical_or(new_mask[lower_index], N.logical_and(mask[upper_index], upper_mask), new_mask[lower_index]) N.logical_and(new_mask, N.logical_not(mask), new_mask) N.logical_or(mask, new_mask, mask) if N.sum(N.ravel(new_mask)) == 0: break return mask def dataDump(self, filename): outfile = file(filename, 'w') data = N.ravel(N.transpose(self.data)) data = 10000. * data / N.maximum.reduce(data) data.shape = (len(data) / 7, 7) for line in data: for number in line: outfile.write('%.1f ' % number) outfile.write('\n') outfile.close() def writeVTK(self, filename): import pyvtk origin = N.array([self.x_axis[0], self.y_axis[0], self.z_axis[0]]) spacing = N.array([self.x_axis[1], self.y_axis[1], self.z_axis[1]]) \ - origin values = pyvtk.Scalars(N.ravel(N.transpose(self.data)), 'electron density') data = pyvtk.VtkData( pyvtk.StructuredPoints(self.data.shape, origin, spacing), 'Density map', pyvtk.PointData(values)) data.tofile(filename, format='binary') def view(self, gmodule, lower, upper, file=None): scene = gmodule.Scene() scale = gmodule.ColorScale(1.) size = 0.5 * min(self.x_axis[1], self.y_axis[1], self.z_axis[1]) for i in range(self.nx): for j in range(self.ny): for k in range(self.nz): value = self.data[i, j, k] if value > lower and value < upper: center = Vector(self.x_axis[i], self.y_axis[j], self.z_axis[k]) m = gmodule.Material(diffuse_color=scale(value)) object = gmodule.Sphere(center, size, material=m) scene.addObject(object) if file is None: scene.view() else: scene.writeToFile(file) def viewVMD(self, filename=None, pdb_filename=None): run_vmd = 0 if filename is None: filename = tempfile.mktemp() run_vmd = 1 file = open(filename, 'w') if pdb_filename is not None: file.write('mol load pdb %s\n' % pdb_filename) file.write('mol volume top "Electron Density" \\\n') x_origin = self.x_axis[0] / Units.Ang y_origin = self.y_axis[0] / Units.Ang z_origin = self.z_axis[0] / Units.Ang x_length = self.x_axis[-1] / Units.Ang - x_origin y_length = self.y_axis[-1] / Units.Ang - y_origin z_length = self.z_axis[-1] / Units.Ang - z_origin file.write(' {%f %f %f} \\\n' % (x_origin, y_origin, z_origin)) file.write(' {%f 0. 0.} \\\n' % x_length) file.write(' {0. %f 0.} \\\n' % y_length) file.write(' {0. 0. %f} \\\n' % z_length) file.write(' %d %d %d \\\n' % self.data.shape) file.write(' {') factor = 1. / N.maximum.reduce(N.ravel(self.data)) for iz in range(self.data.shape[2]): for iy in range(self.data.shape[1]): for ix in range(self.data.shape[0]): file.write(str(factor * self.data[ix, iy, iz]) + ' ') file.write('}\n') file.write('mol addrep top\nmol modstyle 1 top isosurface\n') if run_vmd: file.write('file delete %s\n' % filename) file.close() if run_vmd: os.system('vmd -e ' + filename + ' 1> /dev/null 2>&1') def writeXPlor(self, filename): from Scientific.IO.FortranFormat import FortranFormat, FortranLine file = open(filename, 'w') file.write('\n 1 !NTITLE\n') file.write('REMARKS Electronic density map\n') data = [ self.data.shape[0], 1, self.data.shape[0], self.data.shape[1], 1, self.data.shape[1], self.data.shape[2], 1, self.data.shape[2] ] file.write(str(FortranLine(data, '9I8')) + '\n') x = (self.x_axis[-1] - self.x_axis[0]) / Units.Ang y = (self.y_axis[-1] - self.y_axis[0]) / Units.Ang z = (self.z_axis[-1] - self.z_axis[0]) / Units.Ang data = [x, y, z] + 3 * [90.] file.write(str(FortranLine(data, '6E12.5')) + '\n') file.write('ZYX\n') map_data = N.ravel(self.data) map_data = map_data / N.maximum.reduce(map_data) average = N.sum(map_data) / len(map_data) sd = N.sqrt(N.sum((map_data - average)**2) / len(map_data)) map_data.shape = self.data.shape for i in range(self.data.shape[2]): file.write(str(FortranLine([i], 'I8')) + '\n') data = list(N.ravel(N.transpose(map_data[:, :, i]))) while data: file.write(str(FortranLine(data[:6], '%dE12.5' % min(6, len(data)))) \ + '\n') data = data[6:] file.write(str(FortranLine([-9999], 'I8')) + '\n') file.write(str(FortranLine([average, sd], '2(E12.4,1X)')) + '\n') file.close()
x = D(10, index=0, order=2) y = D(0, index=1, order=2) z = D(1, index=2, order=2) r = somefunc(x, y, z) print r # (40, [3, -1, 20], [[0, 0, 0], [0, 0, 0], [0, 0, 20]]) print 'd^2(somefunc)/dzdx:', r[2][2][0] # 0 print 'd^2(somefunc)/dz^2:', r[2][2][2] # 20 print '\n\ntesting interpolation:' from Scientific.Functions.Interpolation \ import InterpolatingFunction as Ip t = linspace(0, 10, 101) v = sin(t) vi = Ip((t, ), v) # interpolate and compare with exact result: print 'interpolated:', vi(5.05), ' exact:', sin(5.05) # interpolate the derivative of v: vid = vi.derivative() print 'interpolated derivative:', vid(5.05), ' exact:', cos(5.05) # compute the integral of v over all t values: print 'definite integral:', vi.definiteIntegral(), \ ' exact:', -cos(t[-1]) - (-cos(t[0])) # add path to Grid2D (for testing interpolation on a 2D grid): sys.path.insert(0, os.path.join(os.environ['scripting'], 'src', 'py', 'examples')) from Grid2D import Grid2D g = Grid2D(dx=0.1, dy=0.2) f = g(lambda x, y: sin(pi * x) * sin(pi * y))
def get_ld_grid(photband, **kwargs): """ Retrieve an interpolating grid for the LD coefficients Check outcome: #>>> bands = ['GENEVA.U', 'GENEVA.B', 'GENEVA.G', 'GENEVA.V'] #>>> f_ld_grid = get_ld_grid(bands) #>>> ff = pyfits.open(_atmos['file']) #>>> all(ff['GENEVA.U'].data[257][2:]==f_ld_grid(ff['GENEVA.U'].data[257][0],ff['GENEVA.U'].data[257][1])[0:5]) #True #>>> all(ff['GENEVA.G'].data[257][2:]==f_ld_grid(ff['GENEVA.G'].data[257][0],ff['GENEVA.G'].data[257][1])[10:15]) #True #>>> ff.close() #Make some plots: #>>> photband = ['GENEVA.V'] #>>> f_ld = get_ld_grid(photband) #>>> logg = 4.0 #>>> mu = linspace(0,1,100) #>>> p = figure() #>>> p = gcf().canvas.set_window_title('test of function <get_ld_grid>') #>>> for teff in linspace(9000,12000,19): #... out = f_ld(teff,logg) #... a1x,a2x,a3x,a4x, I_x1 = out.reshape((len(photband),5)).T #... p = subplot(221);p = title('Interpolation of absolute intensities') #... p = plot(teff,I_x1,'ko') #... p = subplot(222);p = title('Interpolation of LD coefficients') #... p = scatter(4*[teff],[a1x,a2x,a3x,a4x],c=range(4),vmin=0,vmax=3,cmap=cm.spectral,edgecolors='none') #... p = subplot(223);p = title('Without absolute intensity') #... p = plot(mu,ld_eval(mu,[a1x,a2x,a3x,a4x]),'-') #... p = subplot(224);p = title('With absolute intensity') #... p = plot(mu,I_x1*ld_eval(mu,[a1x,a2x,a3x,a4x]),'-') """ #-- retrieve the grid points (unique values) teffs, loggs = get_ld_grid_dimensions(**kwargs) teffs_grid = np.sort(np.unique1d(teffs)) loggs_grid = np.sort(np.unique1d(loggs)) coeff_grid = np.zeros( (len(teffs_grid), len(loggs_grid), 5 * len(photband))) #-- get the FITS-file containing the tables gridfile = get_file(**kwargs) #-- fill the grid ff = pyfits.open(gridfile) for pp, iband in enumerate(photband): teffs = ff[iband].data.field('Teff') loggs = ff[iband].data.field('logg') for ii, (iteff, ilogg) in enumerate(zip(teffs, loggs)): indext = np.searchsorted(teffs_grid, iteff) indexg = np.searchsorted(loggs_grid, ilogg) #-- array and list are added for backwards compatibility with some # pyfits versions coeff_grid[indext, indexg, 5 * pp:5 * (pp + 1)] = np.array( list(ff[iband].data[ii]))[2:] ff.close() #-- make an interpolating function f_ld_grid = InterpolatingFunction([teffs_grid, loggs_grid], coeff_grid) return f_ld_grid
import pandas as pd import numpy as np from Scientific.Functions.Interpolation import InterpolatingFunction df_EC = pd.read_csv("EC.csv") df_DL = pd.read_csv("DL.csv") gt = np.arange(1,4,1) g1 = np.arange(20,55,15) g2 = np.arange(20,55,15) WCU = np.arange(2,7,2) temp = df_EC.iloc[0:27] temp2 = temp.as_matrix() data = temp2.reshape(len(gt),len(g1),len(g2)) axes = (gt,g1,g2) print(axes) print(data) f = InterpolatingFunction(axes, data) print(f(2.5,25.5,40.5))
def incoherentScatteringFunction(self, q, time_range=(0., None, None), subset=None, random_vectors=15, first_mode=6): """ :param q: the angular wavenumber :type q: float :param time_range: the time values at which the mean-square displacement is evaluated, specified as a range tuple (first, last, step). The defaults are first=0, last= 20 times the longest vibration perdiod, and step defined such that 300 points are used in total. :type time_range: tuple :param subset: the subset of the universe used in the calculation (default: the whole universe) :type subset: :class:~MMTK.Collections.GroupOfAtoms :param random_vectors: the number of random direction vectors used in the orientational average :type random_vectors: int :param first_mode: the first mode to be taken into account for the fluctuation calculation. The default value of 6 is right for molecules in vacuum. :type first_mode: int :returns: the Incoherent Scattering Function as a function of time :rtype: Scientific.Functions.Interpolation.InterpolatingFunction """ if subset is None: subset = self.universe mask = subset.booleanMask() weights_inc = self.universe.getParticleScalar('b_incoherent') weights_inc = N.repeat(weights_inc.array**2, mask.array) weights_inc = weights_inc / N.add.reduce(weights_inc) friction = N.repeat(self.friction.array, mask.array) mass = N.repeat(self.universe.masses().array, mask.array) r = N.repeat(self.universe.configuration().array, mask.array) first, last, step = (time_range + (None, None))[:3] if last is None: last = 3. / self.weighedMode(first_mode).inv_relaxation_time if step is None: step = (last - first) / 300. time = N.arange(first, last, step) natoms = subset.numberOfAtoms() kT = Units.k_B * self.temperature finc = N.zeros((len(time), ), N.Float) eisf = 0. random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: phase = N.exp(-1.j * q * N.dot(r, v.array)) faat = N.zeros((natoms, len(time)), N.Float) eisf_sum = N.zeros((natoms, ), N.Float) for i in range(first_mode, self.nmodes): irt = self.rawMode(i).inv_relaxation_time d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \ / N.sqrt(friction) ft = (N.exp(-irt * time) - 1.) / irt N.add(faat, d[:, N.NewAxis]**2 * ft[N.NewAxis, :], faat) N.add(eisf_sum, -d**2 / irt, eisf_sum) N.add(finc, N.sum(weights_inc[:, N.NewAxis] * N.exp(kT * faat), 0), finc) eisf = eisf + N.sum(weights_inc * N.exp(kT * eisf_sum)) return InterpolatingFunction((time, ), finc / len(random_vectors))
def coherentScatteringFunction(self, q, time_range=(0., None, None), subset=None, weights=None, random_vectors=15, first_mode=6): """ :param q: the angular wavenumber :type q: float :param time_range: the time values at which the mean-square displacement is evaluated, specified as a range tuple (first, last, step). The defaults are first=0, last= 20 times the longest vibration perdiod, and step defined such that 300 points are used in total. :type time_range: tuple :param subset: the subset of the universe used in the calculation (default: the whole universe) :type subset: :class:~MMTK.Collections.GroupOfAtoms :param weights: the weight to be given to each atom in the average (default: coherent scattering lengths) :type weights: :class:~MMTK.ParticleProperties.ParticleScalar :param random_vectors: the number of random direction vectors used in the orientational average :type random_vectors: int :param first_mode: the first mode to be taken into account for the fluctuation calculation. The default value of 6 is right for molecules in vacuum. :type first_mode: int :returns: the Coherent Scattering Function as a function of time :rtype: Scientific.Functions.Interpolation.InterpolatingFunction """ if subset is None: subset = self.universe if weights is None: weights = self.universe.getParticleScalar('b_coherent') mask = subset.booleanMask() weights = N.repeat(weights.array, mask.array) weights = weights / N.sqrt(N.add.reduce(weights * weights)) friction = N.repeat(self.friction.array, mask.array) r = N.repeat(self.universe.configuration().array, mask.array) first, last, step = (time_range + (None, None))[:3] if last is None: last = 3. / self.rawMode(first_mode).inv_relaxation_time if step is None: step = (last - first) / 300. time = N.arange(first, last, step) natoms = subset.numberOfAtoms() kT = Units.k_B * self.temperature fcoh = N.zeros((len(time), ), N.Complex) random_vectors = Random.randomDirections(random_vectors) for v in random_vectors: phase = N.exp(-1.j * q * N.dot(r, v.array)) for ai in range(natoms): fbt = N.zeros((natoms, len(time)), N.Float) for i in range(first_mode, self.nmodes): irt = self.rawMode(i).inv_relaxation_time d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \ / N.sqrt(friction) ft = N.exp(-irt * time) / irt N.add(fbt, d[ai] * d[:, N.NewAxis] * ft[N.NewAxis, :], fbt) N.add(fbt, (-0.5 / irt) * (d[ai]**2 + d[:, N.NewAxis]**2), fbt) N.add( fcoh, weights[ai] * phase[ai] * N.dot(weights * N.conjugate(phase), N.exp(kT * fbt)), fcoh) return InterpolatingFunction((time, ), fcoh.real / len(random_vectors))
x = D(10, index=0, order=2) y = D(0, index=1, order=2) z = D(1, index=2, order=2) r = somefunc(x, y, z) print r # (40, [3, -1, 20], [[0, 0, 0], [0, 0, 0], [0, 0, 20]]) print "d^2(somefunc)/dzdx:", r[2][2][0] # 0 print "d^2(somefunc)/dz^2:", r[2][2][2] # 20 print "\n\ntesting interpolation:" from Scientific.Functions.Interpolation import InterpolatingFunction as Ip t = linspace(0, 10, 101) v = sin(t) vi = Ip((t,), v) # interpolate and compare with exact result: print "interpolated:", vi(5.05), " exact:", sin(5.05) # interpolate the derivative of v: vid = vi.derivative() print "interpolated derivative:", vid(5.05), " exact:", cos(5.05) # compute the integral of v over all t values: print "definite integral:", vi.definiteIntegral(), " exact:", -cos(t[-1]) - (-cos(t[0])) # add path to Grid2D (for testing interpolation on a 2D grid): sys.path.insert(0, os.path.join(os.environ["scripting"], "src", "py", "examples")) from Grid2D import Grid2D g = Grid2D(dx=0.1, dy=0.2) f = g(lambda x, y: sin(pi * x) * sin(pi * y)) fi = Ip((g.xcoor, g.ycoor), f)
def get_grid_mesh(wave=None, teffrange=None, loggrange=None, **kwargs): """ Return InterpolatingFunction spanning the available grid of spectrum models. WARNING: the grid must be entirely defined on a mesh grid, but it does not need to be equidistant. It is thus the user's responsibility to know whether the grid is evenly spaced in logg and teff You can supply your own wavelength range, since the grid models' resolution are not necessarily homogeneous. If not, the first wavelength array found in the grid will be used as a template. It might take a long a time and cost a lot of memory if you load the entire grid. Therefor, you can also set range of temperature and gravity. @param wave: wavelength to define the grid on @type wave: ndarray @param teffrange: starting and ending of the grid in teff @type teffrange: tuple of floats @param loggrange: starting and ending of the grid in logg @type loggrange: tuple of floats @return: wavelengths, teffs, loggs and fluxes of grid, and the interpolating function @rtype: (1Darray,1Darray,1Darray,3Darray,InterpolatingFunction) """ #-- get the dimensions of the grid teffs, loggs = get_grid_dimensions(**kwargs) #-- build flux grid, assuming a perfectly sampled grid (needs not to be # equidistant) if teffrange is not None: sa = (teffrange[0] <= teffs) & (teffs <= teffrange[1]) teffs = teffs[sa] if loggrange is not None: sa = (loggrange[0] <= loggs) & (loggs <= loggrange[1]) loggs = loggs[sa] #-- clip if necessary teffs = list(set(list(teffs))) loggs = list(set(list(loggs))) teffs = np.sort(teffs) loggs = np.sort(loggs) if wave is not None: flux = np.ones((len(teffs), len(loggs), len(wave))) cont = np.ones((len(teffs), len(loggs), len(wave))) #-- run over teff and logg, and interpolate the models onto the supplied # wavelength range gridfile = get_file(**kwargs) ff = pf.open(gridfile) for i, teff in enumerate(teffs): for j, logg in enumerate(loggs): try: mod_name = "T%05d_logg%01.02f" % (teff, logg) mod = ff[mod_name] wave_ = mod.data.field( 'wavelength') #array(mod.data.tolist())[:,0] flux_ = mod.data.field('flux') #array(mod.data.tolist())[:,1] cont_ = mod.data.field('cont') #array(mod.data.tolist())[:,1] #-- if there is no wavelength range given, we assume that # the whole grid has the same resolution, and the first # wave-array will be used as a template if wave is None: wave = wave_ flux = np.ones((len(teffs), len(loggs), len(wave))) cont = np.ones((len(teffs), len(loggs), len(wave))) except KeyError: continue #-- it could be that we're lucky and the grid is completely # homogeneous. In that case, there is no need for interpolation try: flux[i, j, :] = flux_ cont[i, j, :] = cont_ except: flux[i, j, :] = np.interp(wave, wave_, flux_) cont[i, j, :] = np.interp(wave, wave_, cont_) flux_grid = InterpolatingFunction([np.log10(teffs), loggs], flux) cont_grid = InterpolatingFunction([np.log10(teffs), loggs], cont) #logger.info('Constructed spectrum interpolation grid') return wave, teffs, loggs, flux, flux_grid, cont_grid