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 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 correlation(inputSeries1, inputSeries2=None): """Returns the numerical correlation between two signals. @param inputSeries1: the first signal. @type inputSeries1: NumPy array @param inputSeries2: if not None, the second signal otherwise the correlation will be an autocorrelation. @type inputSeries2: NumPy array or None @return: the result of the numerical correlation. @rtype: NumPy array @note: if |inputSeries1| is a multidimensional array the correlation calculation is performed on the first dimension. @note: The correlation is computed using the FCA algorithm. """ # The signal must not be empty. if len(inputSeries1) <= 0: raise Error('One or both time series are empty.') # The length of inputSeries1 is stored in inputSeries1Length inputSeries1Length = len(inputSeries1) # extendedLength = 2*len(inputSeries1) extendedLength = 2 * inputSeries1Length # The FCA algorithm: # 1) computation of the FFT of inputSeries1 zero-padded until extendedLength # The computation is done along the 0-axis FFTSeries1 = fft(inputSeries1, extendedLength, 0) if inputSeries2 is None: # Autocorrelation case FFTSeries2 = FFTSeries1 else: # 2) computation of the FFT of inputSeries2 zero-padded until extendedLength # The computation is done along the 0-axis FFTSeries2 = fft(inputSeries2, extendedLength, 0) # 3) Product between FFT(inputSeries1)* and FFT(inputSeries2) FFTSeries1 = N.conjugate(FFTSeries1) * FFTSeries2 # 4) inverse FFT of the product # The computation is done along the 0-axis FFTSeries1 = inverse_fft(FFTSeries1, len(FFTSeries1), 0) # This refers to (1/(N-m))*Sab in the published algorithm. # This is the correlation function defined for positive indexes only. if len(FFTSeries1.shape) == 1: corr = FFTSeries1.real[:inputSeries1Length] / ( inputSeries1Length - N.arange(inputSeries1Length)) else: corr = N.add.reduce(FFTSeries1.real[:inputSeries1Length], 1) / ( inputSeries1Length - N.arange(inputSeries1Length)) return corr
def testRetrieval(self): x = N.arange(0., 1., 0.1) y = N.arange(0., 2., 0.1) v = x[:, N.NewAxis] * y[N.NewAxis, :] f = IF((x, y), v) for ix, xp in enumerate(x): for iy, yp in enumerate(y): self.assertEqual(f(xp, yp), v[ix, iy])
def testAxes(self): x = N.arange(0., 1., 0.1) y = N.arange(0., 2., 0.1) v = x[:, N.NewAxis] * y[N.NewAxis, :] self.assertRaises(ValueError, lambda: IF((x[:-2], y), v)) self.assertRaises(ValueError, lambda: IF((x, y[1:]), v)) self.assertRaises(ValueError, lambda: IF((x[:, N.NewAxis], y), v)) self.assertRaises(ValueError, lambda: IF((x, y[::-1]), v)) self.assertRaises(ValueError, lambda: IF((x, 0 * y), v))
def AutoCorrelationFunction(series): """ Autocorrelation function calculated by FFT method """ if len(series.shape) == 1: return acf(series) / (len(series) - N.arange(len(series))) else: return acf(series) / (len(series) - N.arange(len(series)))[:, N.NewAxis]
def _setField(self, data): points = [] values = [] colors = [] default_color = Color.ColorByName('black') for min, max, atoms in self.box.partitions(): center = 0.5 * (min + max) points.append(center.array) v = data.zero() total_weight = 0. color = default_color for a in atoms: d = a.position() - center weight = N.exp(-d * d / self.box.partition_size**2) v = v + weight * data[a] total_weight = total_weight + weight c = default_color try: c = a.color except AttributeError: pass if isinstance(c, basestring): c = Color.ColorByName(c) color = color + c values.append(v / total_weight) colors.append(color) min = N.minimum.reduce(points) max = N.maximum.reduce(points) axes = (N.arange(min[0], max[0] + 1, self.box.partition_size), N.arange(min[1], max[1] + 1, self.box.partition_size), N.arange(min[2], max[2] + 1, self.box.partition_size)) array = N.zeros( tuple(map(len, axes)) + data.value_rank * (3, ), N.Float) inside = N.zeros(tuple(map(len, axes)), N.Float) for p, v in zip(points, values): indices = N.floor((p - min) / self.box.partition_size + 0.5) indices = tuple(indices.astype(N.Int)) array[indices] = v inside[indices] = 1. self.field = self.field_class(axes, array, data.zero()) inside = TensorAnalysis.ScalarField(axes, inside).gradient().length() self.points = [] self.colors = [] for i in range(len(points)): p = points[i] test = 0 try: test = apply(inside, tuple(p)) > 1.e-10 except ValueError: pass if test: self.points.append(p) self.colors.append(colors[i])
def _setField(self, data): points = [] values = [] colors = [] default_color = Color.ColorByName('black') for min, max, atoms in self.box.partitions(): center = 0.5*(min+max) points.append(center.array) v = data.zero() total_weight = 0. color = default_color for a in atoms: d = a.position()-center weight = Numeric.exp(-d*d/self.box.partition_size**2) v = v + weight*data[a] total_weight = total_weight + weight c = default_color try: c = a.color except AttributeError: pass if type(c) == type(''): c = Color.ColorByName(c) color = color + c values.append(v/total_weight) colors.append(color) min = Numeric.minimum.reduce(points) max = Numeric.maximum.reduce(points) axes = (Numeric.arange(min[0], max[0]+1, self.box.partition_size), Numeric.arange(min[1], max[1]+1, self.box.partition_size), Numeric.arange(min[2], max[2]+1, self.box.partition_size)) array = Numeric.zeros(tuple(map(len, axes)) + data.value_rank*(3,), Numeric.Float) inside = Numeric.zeros(tuple(map(len, axes)), Numeric.Float) for p, v in zip(points, values): indices = Numeric.floor((p-min)/self.box.partition_size+0.5) indices = tuple(indices.astype(Numeric.Int)) array[indices] = v inside[indices] = 1. self.field = self.field_class(axes, array, data.zero()) inside = TensorAnalysis.ScalarField(axes, inside).gradient().length() self.points = [] self.colors = [] for i in range(len(points)): p = points[i] test = 0 try: test = apply(inside, tuple(p)) > 1.e-10 except ValueError: pass if test: self.points.append(p) self.colors.append(colors[i])
def symmetricTensorBasis(cell, space_group): from CDTK.Crystal import UnitCell subspace = 1. * N.equal.outer(N.arange(6), N.arange(6)) for tr in cartesianCoordinateSymmetryTransformations(cell, space_group): rot = symmetricTensorRotationMatrix(tr.tensor.array) ev, axes = LA.eigenvectors(rot) new_subspace = [] for i in range(6): if abs(ev[i] - 1.) < 1.e-12: p = N.dot(N.transpose(subspace), N.dot(subspace, axes[i].real)) new_subspace.append(p) m, s, subspace = LA.singular_value_decomposition(N.array(new_subspace)) nb = N.sum(s / s[0] > 1.e-12) subspace = subspace[:nb] return [SymmetricTensor(a) for a in subspace]
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 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 _dihedralTerm(self, n, phase, V): mod_file = self.mod_template % \ (V/(Units.kcal/Units.mol), phase/Units.deg, n) ff = Amber99ForceField(mod_files=[StringIO(mod_file)]) self.universe.setForceField(ff) param = self.universe.energyEvaluatorParameters() i1, i2, i3, i4, n_test, phase_test, V_test = \ param['cosine_dihedral_term'][0] self.assertEqual(n_test, n) # The accuracy is no better than five digits because the # parameters pass through a text representation. self.assertAlmostEqual(phase_test, phase, 5) self.assertAlmostEqual(V_test, V, 5) two_pi = 2. * N.pi m = self.universe[0] for angle in N.arange(0., two_pi, 0.1): m.C4.setPosition(Vector(N.cos(angle), N.sin(angle), 1.)) e = self.universe.energyTerms()['cosine dihedral angle'] da = self.universe.dihedral(m.C1, m.C2, m.C3, m.C4) e_ref = V * (1. + N.cos(n * angle - phase)) self.assertAlmostEqual(angle % two_pi, da % two_pi, 14) self.assertAlmostEqual(e, e_ref, 5) self._gradientTest() self._forceConstantTest()
def generateDos(): "Generates DOS" temperature = TEMPERATURE # Defaults: begin = 0 end = -1 step = 1 trajectoryPath = NCFILE log = "" # Starting log log += "Using file %s as input...\n" % trajectoryPath trajectory = Trajectory(None, trajectoryPath, 'r') if end == -1: end = len(trajectory.time) timeinfo = '%d:%d:%d' % (begin, end, step) log += 'The complete trajectory size is %d elements\n' % len(trajectory.time) log += "\nAnalysing trajectory from position %d to postion %d with step %d:\n" % (begin, end, step) log += 'Temperature = %s\n' % temperature parameters = { 'trajectory': trajectory, 'timeinfo' : timeinfo, 'differentiation': 0, 'projection': 'no', 'fftwindow' : 10.0, 'subset': 'all', 'deuteration': 'no', 'weights': 'equal', 'dos': 'dos.nc', 'pyroserver': 'monoprocessor', } dos = CartesianDensityOfStates_serial( parameters = parameters, statusBar = None) dos.runAnalysis() frequencies = N.arange(dos.nFrames)/(2.0*dos.nFrames*dos.dt) DOS = dos.DOS/dos.DOS.sum() s = '' for f, g in zip(frequencies, DOS): s += '%f %f\n' % (f, g) open(DOSFILE, 'w').write(s) arg = frequencies[1:]/temperature/KelvinToTeraHz exponent = numpy.exp(arg) F = temperature*( 0.5*arg + numpy.log(1.0 - 1.0/exponent ))*DOS[1:] log += 'Free Energy: %s\n' % F.sum() n = 1.0/(exponent - 1.0) s_osc = (1.0 + n[:])*numpy.log(1.0 + n[:]) - n[:]*numpy.log(n[:]) entropy1 = (DOS[1:]*(numpy.log(temperature*KelvinToTeraHz/frequencies[1:])+1.0)).sum() entropy2 = (DOS[1:]*s_osc).sum() log += 'entropy = %s\n' % entropy2 open(OUTPUT, 'w').write(log) # Store log to output file
def reduceToRange(self, first, last): """ Discards all modes outside a given range of mode numbers. This is done to reduce memory requirements, especially before saving the modesto a file. :param first: the number of the first mode to be kept :param last: the number of the last mode to be kept - 1 """ junk1 = list(self.sort_index[:first]) junk2 = list(self.sort_index[last:]) junk1.sort() junk2.sort() if junk1 == range(0, first) and \ junk2 == range(last, len(self.sort_index)): # This is the most frequent case. It can be handled # without copying the mode array. for array in self._internal_arrays: setattr(self, array, getattr(self, array)[first:last]) self.sort_index = self.sort_index[first:last] - first else: keep = self.sort_index[first:last] for array in self._internal_arrays: setattr(self, array, N.take(getattr(self, array), keep)) self.sort_index = N.arange(0, last - first) self.nmodes = last - first
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 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 meanSquareDisplacement(self, subset=None, weights=None, time_range = (0., None, None), tau=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= 20 times the longest vibration perdio, and step defined such that 300 points are used in total. """ if self.temperature is None: raise ValueError("no temperature available") 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 first, last, step = (time_range + (None, None))[:3] if last is None: last = 20./self[first_mode].frequency if step is None: step = (last-first)/300. time = N.arange(first, last, step) if tau is None: damping = 1. else: damping = N.exp(-(time/tau)**2) msd = N.zeros(time.shape, N.Float) for i in range(first_mode, self.nmodes): mode = self[i] omega = 2.*N.pi*mode.frequency d = (weights*(mode*mode)).sumOverParticles() N.add(msd, d*(1.-damping*N.cos(omega*time)), msd) return InterpolatingFunction((time,), msd)
def EISF(self, q_range=(0., 15.), subset=None, weights=None, random_vectors=15, first_mode=6): if self.temperature is None: raise ValueError("no temperature available") 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 = MMTK.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self[i] f = f + mode.dyadicProduct(mode) eisf = N.zeros(q.shape, N.Float) for i in range(random_vectors): v = MMTK.Random.randomDirection() 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 / random_vectors)
def _dihedralTerm(self, n, phase, V): mod_file = self.mod_template % \ (V/(Units.kcal/Units.mol), phase/Units.deg, n) ff = Amber99ForceField(mod_files=[StringIO(mod_file)]) self.universe.setForceField(ff) param = self.universe.energyEvaluatorParameters() i1, i2, i3, i4, n_test, phase_test, V_test = \ param['cosine_dihedral_term'][0] self.assertEqual(n_test, n) # The accuracy is no better than five digits because the # parameters pass through a text representation. self.assertAlmostEqual(phase_test, phase, 5) self.assertAlmostEqual(V_test, V, 5) two_pi = 2.*N.pi m = self.universe[0] for angle in N.arange(0., two_pi, 0.1): m.C4.setPosition(Vector(N.cos(angle), N.sin(angle), 1.)) e = self.universe.energyTerms()['cosine dihedral angle'] da = self.universe.dihedral(m.C1, m.C2, m.C3, m.C4) e_ref = V*(1.+N.cos(n*angle-phase)) self.assertAlmostEqual(angle % two_pi, da % two_pi, 14) self.assertAlmostEqual(e, e_ref, 5) self._gradientTest() self._forceConstantTest()
def Generate_QShells(qShells): genQShells = [] if isinstance(qShells, (list, tuple)): genQShells = qShells elif isinstance(qShells, str): for qInter in [v.strip() for v in qShells.split(";")]: qMin, qMax, dQ = [float(v) for v in qInter.split(":")] temp = N.arange(qMin, qMax + 0.001 * dQ, dQ).tolist() if temp[-1] > qMax: del temp[-1] genQShells.extend(temp) else: raise Error("%s: invalid format for qshells." % genQShells) genQShells = [v for v in sorted(set(genQShells)) if v > 0.0] if len(genQShells) == 0: raise Error("%s triggered emptry qshells generation." % genQShells) return genQShells
def reduceToRange(self, first, last): """ Discards all modes outside a given range of mode numbers. This is done to reduce memory requirements, especially before saving the modesto a file. :param first: the number of the first mode to be kept :param last: the number of the last mode to be kept - 1 """ junk1 = list(self.sort_index[:first]) junk2 = list(self.sort_index[last:]) junk1.sort() junk2.sort() if junk1 == range(0, first) and \ junk2 == range(last, len(self.sort_index)): # This is the most frequent case. It can be handled # without copying the mode array. for array in self._internal_arrays: setattr(self, array, getattr(self, array)[first:last]) self.sort_index = self.sort_index[first:last]-first else: keep = self.sort_index[first:last] for array in self._internal_arrays: setattr(self, array, N.take(getattr(self, array), keep)) self.sort_index = N.arange(0, last-first) self.nmodes = last-first
def EISF(self, q_range = (0., 15.), subset=None, weights = None, random_vectors = 15, first_mode = 6): if self.temperature is None: raise ValueError("no temperature available") 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 = MMTK.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self[i] f = f + mode.dyadicProduct(mode) eisf = N.zeros(q.shape, N.Float) for i in range(random_vectors): v = MMTK.Random.randomDirection() 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/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 __getitem__(self, item): if not isinstance(item, int): return SubVariable(self, N.arange(len(self)))[item] if item < 0: item = item + len(self.trajectory) if item >= len(self.trajectory): raise IndexError if self.name == 'configuration': if self.box_size is None: box = None elif len(self.box_size.shape) == 3: bs = self.trajectory.block_size box = self.box_size[item/bs, :, item%bs].astype(N.Float) else: box = self.box_size[item].astype(N.Float) array = ParticleProperties.Configuration(self.universe, self.trajectory.trajectory.readParticleVector(self.name, item), box) elif 'xyz' in self.var.dimensions: array = ParticleProperties.ParticleVector(self.universe, self.trajectory.trajectory.readParticleVector(self.name, item)) else: array = ParticleProperties.ParticleScalar(self.universe, self.trajectory.trajectory.readParticleScalar(self.name, item)) return array
def plotBox(self, name, data, data_range=None): box = Frame(self, border=2, relief=SUNKEN) box.pack(side=TOP, fill=BOTH, expand=YES) frame = Frame(box, background='grey') frame.pack(side=TOP, fill=X, expand=NO) Label(frame, text=string.capitalize(string.join( string.split(name , '_'), ' ')), background='grey').pack(side=LEFT) if data_range is None: min = Numeric.minimum.reduce(data[:,1]) max = Numeric.maximum.reduce(data[:,1]) min, max = plotRange(min, max) else: min, max = data_range plot_objects = [] plot_data = data time = plot_data[:,0] jumps = Numeric.repeat(Numeric.arange(len(time)-1), Numeric.less(time[1:], time[:-1]))+1 for i in self.master.restarts: plot_objects.append(PolyLine([(self.time[i], min), (self.time[i], max)], color='black', stipple='gray25')) plot_objects.insert(0, PolyLine(plot_data, color = 'red')) plot = PlotCanvas(box, 400, 100, zoom=1, select=self.master._selectRange) plot.pack(side=LEFT, fill=BOTH, expand=YES) plot.draw(PlotGraphics(plot_objects), 'automatic', (min, max)) plot.bind('<Double-Button-1>', lambda event, d=plot_data: externalPlot(d)) self.registerPlot(plot) self.setSelection(plot)
def __init__(self, master, trajectory): Tkwindow.__init__(self, master) self.filename = None if type(trajectory) == type(''): if string.find(trajectory, ':') >= 0 and tmanager is not None: self.filename = trajectory self.inspector = tmanager.trajectoryInspector(trajectory) self.inspector.reopen() else: self.filename = trajectory self.inspector = TrajectoryInspector(trajectory) else: self.inspector = TrajectoryInspector(trajectory) if self.filename is not None: self.title(self.filename) self.description = self.inspector.description() self.universe = None self.categories = categorizeVariables(self.inspector.variableNames()) step_number = Numeric.array(self.inspector.readScalarVariable('step')) jumps = Numeric.less(step_number[1:]-step_number[:-1], 0) self.restarts = Numeric.repeat(Numeric.arange(len(jumps)), jumps)+1 self.restarts = list(self.restarts) try: self.time = \ Numeric.array(self.inspector.readScalarVariable('time')) jumps = Numeric.repeat(Numeric.arange(len(self.time)-1), Numeric.less(self.time[1:], self.time[:-1]))+1 if len(jumps) > 0: for jump in jumps[::-1]: dt = self.time[jump-1] + self.time[jump+1] \ - 2*self.time[jump] try: # Numeric typecode = self.time.typecode() except AttributeError: # numpy typecode = self.time.dtype.char self.time[jump:] = (self.time[jump:] + dt).astype(typecode) except KeyError: self.time = 1.*Numeric.arange(self.inspector.numberOfSteps()) self.plotlist = [] self.selection = None self._createMenu() self._createMainBox() self.open()
def __init__(self, master, trajectory): Tkwindow.__init__(self, master) self.filename = None if type(trajectory) == type(''): if string.find(trajectory, ':') >= 0 and tmanager is not None: self.filename = trajectory self.inspector = tmanager.trajectoryInspector(trajectory) self.inspector.reopen() else: self.filename = trajectory self.inspector = TrajectoryInspector(trajectory) else: self.inspector = TrajectoryInspector(trajectory) if self.filename is not None: self.title(self.filename) self.description = self.inspector.description() self.universe = None self.categories = categorizeVariables(self.inspector.variableNames()) step_number = Numeric.array(self.inspector.readScalarVariable('step')) jumps = Numeric.less(step_number[1:] - step_number[:-1], 0) self.restarts = Numeric.repeat(Numeric.arange(len(jumps)), jumps) + 1 self.restarts = list(self.restarts) try: self.time = \ Numeric.array(self.inspector.readScalarVariable('time')) jumps = Numeric.repeat(Numeric.arange(len(self.time) - 1), Numeric.less(self.time[1:], self.time[:-1])) + 1 if len(jumps) > 0: for jump in jumps[::-1]: dt = self.time[jump-1] + self.time[jump+1] \ - 2*self.time[jump] try: # Numeric typecode = self.time.typecode() except AttributeError: # numpy typecode = self.time.dtype.char self.time[jump:] = (self.time[jump:] + dt).astype(typecode) except KeyError: self.time = 1. * Numeric.arange(self.inspector.numberOfSteps()) self.plotlist = [] self.selection = None self._createMenu() self._createMainBox() self.open()
def GaussianWindow(series, alpha=0.): series1 = N.zeros((2 * len(series) - 2, ), N.Float) res = series * N.exp(-0.5 * (alpha * N.arange(len(series)) / (len(series) - 1))**2) series1[:len(series)] = res series1[len(series):] = res[-2:0:-1] return series1
def correlation(inputSeries1, inputSeries2 = None): """Returns the numerical correlation between two signals. @param inputSeries1: the first signal. @type inputSeries1: NumPy array @param inputSeries2: if not None, the second signal otherwise the correlation will be an autocorrelation. @type inputSeries2: NumPy array or None @return: the result of the numerical correlation. @rtype: NumPy array @note: if |inputSeries1| is a multidimensional array the correlation calculation is performed on the first dimension. @note: The correlation is computed using the FCA algorithm. """ # The signal must not be empty. if len(inputSeries1) <= 0: raise Error('One or both time series are empty.') # The length of inputSeries1 is stored in inputSeries1Length inputSeries1Length = len(inputSeries1) # extendedLength = 2*len(inputSeries1) extendedLength = 2*inputSeries1Length # The FCA algorithm: # 1) computation of the FFT of inputSeries1 zero-padded until extendedLength # The computation is done along the 0-axis FFTSeries1 = fft(inputSeries1,extendedLength,0) if inputSeries2 is None: # Autocorrelation case FFTSeries2 = FFTSeries1 else: # 2) computation of the FFT of inputSeries2 zero-padded until extendedLength # The computation is done along the 0-axis FFTSeries2 = fft(inputSeries2,extendedLength,0) # 3) Product between FFT(inputSeries1)* and FFT(inputSeries2) FFTSeries1 = N.conjugate(FFTSeries1)*FFTSeries2 # 4) inverse FFT of the product # The computation is done along the 0-axis FFTSeries1 = inverse_fft(FFTSeries1,len(FFTSeries1),0) # This refers to (1/(N-m))*Sab in the published algorithm. # This is the correlation function defined for positive indexes only. if len(FFTSeries1.shape) == 1: corr = FFTSeries1.real[:inputSeries1Length] / (inputSeries1Length-N.arange(inputSeries1Length)) else: corr = N.add.reduce(FFTSeries1.real[:inputSeries1Length],1) / (inputSeries1Length-N.arange(inputSeries1Length)) return corr
def _addData(self, data): data = N.array(data, N.Float) data = N.repeat(data, N.logical_and(N.less_equal(data, self.max), N.greater_equal(data, self.min))) data = N.floor((data - self.min)/self.bin_width).astype(N.Int) nbins = self.array.shape[0] histo = N.int_sum(N.equal(N.arange(nbins)[:,N.NewAxis], data), -1) histo[-1] = histo[-1] + N.int_sum(N.equal(nbins, data)) self.array[:, 1] = self.array[:, 1] + histo
def _addData(self, data): data = N.array(data, N.Float) data = N.repeat(data, N.logical_and(N.less_equal(data, self.max), N.greater_equal(data, self.min))) data = N.floor((data - self.min)/self.bin_width).astype(N.Int) nbins = self.array.shape[0] histo = N.int_sum(N.equal(N.arange(nbins)[:,N.NewAxis], data), -1) histo[-1] = histo[-1] + N.int_sum(N.equal(nbins, data)) self.array[:, 1] = self.array[:, 1] + histo
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 meanSquareDisplacement(self, subset=None, weights=None, time_range=(0., None, None), tau=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 tau: the relaxation time of an exponential damping factor (default: no damping) :type tau: float :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 self.temperature is None: raise ValueError("no temperature available") 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 first, last, step = (time_range + (None, None))[:3] if last is None: last = 20. / self[first_mode].frequency if step is None: step = (last - first) / 300. time = N.arange(first, last, step) if tau is None: damping = 1. else: damping = N.exp(-(time / tau)**2) msd = N.zeros(time.shape, N.Float) for i in range(first_mode, self.nmodes): mode = self[i] omega = 2. * N.pi * mode.frequency d = (weights * (mode * mode)).sumOverParticles() N.add(msd, d * (1. - damping * N.cos(omega * time)), msd) return InterpolatingFunction((time, ), msd)
def CorrelationFunction(series1, series2, lock=None): n = 1 while n < 2 * len(series1): n = n * 2 FFTSeries1 = fft(series1, n, 0) FFTSeries2 = fft(series2, n, 0) FFTSeries1 = N.conjugate(FFTSeries1) * FFTSeries2 FFTSeries1 = inverse_fft(FFTSeries1, len(FFTSeries1), 0) return FFTSeries1.real[:len(series1)] / \ (len(series1)-N.arange(len(series1)))
def timePrepare(traj, timeInfo=None): """ just preparing a time axis basing on timeInfo given or the size of a trajectory """ if timeInfo is None: timeInfo = (0, len(traj) - 1, 1) time = traj.time[timeInfo[0]:timeInfo[1]:timeInfo[2]] dt = time[1] - time[0] return dt * N.arange(len(time))
def _setup(self, data, nbins, range): if range is None: self.min = N.minimum.reduce(data) self.max = N.maximum.reduce(data) else: self.min, self.max = range self.min = self.min+0. self.max = self.max+0. self.bin_width = (self.max-self.min)/nbins self.array = N.zeros((nbins, 2), N.Float) self.array[:, 0] = self.min + self.bin_width*(N.arange(nbins)+0.5)
def _setup(self, data, nbins, range): if range is None: self.min = N.minimum.reduce(data) self.max = N.maximum.reduce(data) else: self.min, self.max = range self.min = self.min+0. self.max = self.max+0. self.bin_width = (self.max-self.min)/nbins self.array = N.zeros((nbins, 2), N.Float) self.array[:, 0] = self.min + self.bin_width*(N.arange(nbins)+0.5)
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 self.temperature is None: raise ValueError("no temperature available") 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 = MMTK.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self[i] f = f + mode.dyadicProduct(mode) eisf = N.zeros(q.shape, N.Float) for i in range(random_vectors): v = MMTK.Random.randomDirection() 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 / random_vectors)
def getMeanSquareDisplacement(series): MSD = N.zeros((len(series)), N.Float) dsq = series[:, 0]**2 + series[:, 1]**2 + series[:, 2]**2 sum_dsq1 = N.add.accumulate(dsq) sum_dsq2 = N.add.accumulate(dsq[::-1]) sumsq = 2. * sum_dsq1[-1] msd = sumsq - N.concatenate(([0.], sum_dsq1[:-1])) \ - N.concatenate(([0.], sum_dsq2[:-1])) Sab = 2. * N.add.reduce(acf(series, 0), 1) MSD = MSD + (msd - Sab) / (len(series) - N.arange(len(series))) return MSD
def meanSquareDisplacement(self, subset=None, weights=None, time_range = (0., None, None), tau=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 tau: the relaxation time of an exponential damping factor (default: no damping) :type tau: float :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 self.temperature is None: raise ValueError("no temperature available") 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 first, last, step = (time_range + (None, None))[:3] if last is None: last = 20./self[first_mode].frequency if step is None: step = (last-first)/300. time = N.arange(first, last, step) if tau is None: damping = 1. else: damping = N.exp(-(time/tau)**2) msd = N.zeros(time.shape, N.Float) for i in range(first_mode, self.nmodes): mode = self[i] omega = 2.*N.pi*mode.frequency d = (weights*(mode*mode)).sumOverParticles() N.add(msd, d*(1.-damping*N.cos(omega*time)), msd) return InterpolatingFunction((time,), msd)
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 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 self.temperature is None: raise ValueError("no temperature available") 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 = MMTK.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self[i] f = f + mode.dyadicProduct(mode) eisf = N.zeros(q.shape, N.Float) for i in range(random_vectors): v = MMTK.Random.randomDirection() 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/random_vectors)
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 _precomputeArrays(self, mask): # S vectors, their squared length, and the phase factors for # structure calculation. sv, p = self.reflection_set.sVectorArrayAndPhasesForASU() self.sv = N.repeat(sv, mask, axis=1) self.p = N.repeat(p, mask, axis=1) self.ssq = N.add.reduce(self.sv[0]*self.sv[0], axis=1) # Symmetry factors and centricity for all reflections sm = self.reflection_set.symmetryAndCentricityArrays() self.epsilon = N.repeat(sm[:, 0], mask) self.centric = N.repeat(sm[:, 1], mask) self.working_centric_indices = \ N.array(N.repeat(N.arange(self.nreflections), N.logical_and(self.working_set, self.centric)), N.Int32) self.working_acentric_indices = \ N.array(N.repeat(N.arange(self.nreflections), N.logical_and(self.working_set, 1-self.centric)), N.Int32) # Atomic scattering factors for the atoms in the model from CDTK.AtomicScatteringFactors import atomic_scattering_factors e_indices = {} for i in range(self.natoms): e_indices.setdefault(self.elements[i], len(e_indices)) self.element_indices = N.array([e_indices[self.elements[i]] for i in range(self.natoms)], N.Int32) f_atom = N.zeros((len(e_indices), self.nreflections), N.Float) for i in range(self.natoms): a, b = atomic_scattering_factors[self.elements[i]] f_atom[self.element_indices[i], :] = \ N.sum(a[:, N.NewAxis] * N.exp(-b[:, N.NewAxis] * self.ssq[N.NewAxis, :])) self.f_atom = f_atom
def factorial(n): """Returns n! @param n: n. @type: integer @return: n!. @rtype: integer """ # 0! = 1! = 1 if n < 2: return 1 else: # multiply is a ufunc of Numeric module return N.multiply.reduce(N.arange(2, n + 1, typecode=N.Float))
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 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 resolutionShells(self, shells): """ Partition the reflections into resolution shells. :param shells: the resolution shell specification, either a sequence of s values delimiting the shells (one more value than there will be shells), or an integer indicating the number of shells into which the total resolution range will be divided. :type shells: int or sequence of float :return: the resolution shells, each of which has its average s value stored in the attribute 's_avg'. The average is None if the subset is empty. :rtype: sequence of ReflectionSubset """ if isinstance(shells, int): assert shells > 0 s_min, s_max = self.sRange() nshells = shells shells = s_min + N.arange(nshells+1)*((s_max-s_min)/nshells) shells[0] *= 0.99 shells[-1] *= 1.01 else: shells = N.array(shells) nshells = len(shells)-1 assert nshells > 0 assert ((shells[1:]-shells[:-1]) > 0.).all() reflections = [[] for i in range(nshells)] s_sum = N.zeros((nshells,), N.Float) for reflection in self: s = reflection.sVector().length() n = N.sum(s >= shells)-1 if n >= 0 and n < nshells: reflections[n].append(reflection) s_sum[n] += s subsets = [] for i in range(nshells): subset = ReflectionSubset(self, reflections[i]) subset.s_min = shells[i] subset.s_max = shells[i+1] subset.s_middle = 0.5*(shells[i]+shells[i+1]) if reflections[i]: subset.s_avg = s_sum[i]/len(reflections[i]) else: subset.s_avg = None subsets.append(subset) return subsets
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 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 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 calc_msd(series): """Calculates the atomic term. @param atomIndex: the index of the selected atom. @type atomIndex: integer @param trajectory: the trajectory. @type trajectory: MMTK.Trajectory.Trajectory object """ # series = 2D Numeric array. The positions of the selected atom |at| from the first step to the # last step with the selected step increment. # series = trajectory.readParticleTrajectory(atomIndex, first = self.first, last = self.last, skip = self.skip).array # dsq is the squared norm of the position for each time step # dsq refers to DSQ(k) in the published algorithm dsq = N.add.reduce(series * series,1) # sum_dsq1 is the cumulative sum of dsq sum_dsq1 = N.add.accumulate(dsq) # sum_dsq1 is the reversed cumulative sum of dsq sum_dsq2 = N.add.accumulate(dsq[::-1]) # sumsq refers to SUMSQ in the published algorithm sumsq = 2.*sum_dsq1[-1] # this line refers to the instruction SUMSQ <-- SUMSQ - DSQ(m-1) - DSQ(N - m) of the published algorithm # In this case, msd is an array because the instruction is computed for each m ranging from 0 to len(traj) - 1 # So, this single instruction is performing the loop in the published algorithm Saabb = sumsq - N.concatenate(([0.], sum_dsq1[:-1])) - N.concatenate(([0.], sum_dsq2[:-1])) # Saabb refers to SAA+BB/(N-m) in the published algorithm # Sab refers to SAB(m)/(N-m) in the published algorithm Saabb = Saabb / (len(dsq) - N.arange(len(dsq))) Sab = 2.*correlation(series) atomicMSD = Saabb - Sab return atomicMSD
def reduceToRange(self, first, last): """Discards all modes except for those whose numbers are between |first| (inclusive) and |last| (exclusive). This is done to reduce memory requirements, especially before saving the modes to a file.""" junk1 = list(self.sort_index[:first]) junk2 = list(self.sort_index[last:]) junk1.sort() junk2.sort() if junk1 == range(0, first) and \ junk2 == range(last, len(self.sort_index)): # This is the most frequent case. It can be handled # without copying the mode array. for array in self._internal_arrays: setattr(self, array, getattr(self, array)[first:last]) self.sort_index = self.sort_index[first:last]-first else: keep = self.sort_index[first:last] for array in self._internal_arrays: setattr(self, array, N.take(getattr(self, array), keep)) self.sort_index = N.arange(0, last-first) self.nmodes = last-first
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))
def incoherentScatteringFunction(self, q, time_range = (0., None, None), subset=None, weights=None, tau=None, random_vectors=15, first_mode = 6): if self.temperature is None: raise ValueError("no temperature available") 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 = (time_range + (None, None))[:3] if last is None: last = 20./self[first_mode].frequency if step is None: step = (last-first)/400. time = N.arange(first, last, step) if tau is None: damping = 1. else: damping = N.exp(-(time/tau)**2) finc = N.zeros(time.shape, N.Float) random_vectors = MMTK.Random.randomDirections(random_vectors) for v in random_vectors: for a in subset.atomList(): msd = 0. for i in range(first_mode, self.nmodes): mode = self[i] d = (v*mode[a])**2 omega = 2.*N.pi*mode.frequency msd = msd+d*(1.-damping*N.cos(omega*time)) N.add(finc, weights[a]*N.exp(-q*q*msd), finc) return InterpolatingFunction((time,), finc/len(random_vectors))
def __getitem__(self, item): if not isinstance(item, int): return SubTrajectory(self, N.arange(len(self)))[item] if item < 0: item += len(self) if item >= len(self): raise IndexError data = {} for name, var in self.trajectory.file.variables.items(): if 'step_number' not in var.dimensions: continue if 'atom_number' in var.dimensions: if 'xyz' in var.dimensions: array = ParticleProperties.ParticleVector(self.universe, self.trajectory.readParticleVector(name, item)) else: array = ParticleProperties.ParticleScalar(self.universe, self.trajectory.readParticleScalar(name, item)) else: bs = self.block_size if bs == 1: array = var[item] else: if len(var.shape) == 2: array = var[item/bs, item%bs] else: array = var[item/bs, ..., item%bs] data[name] = 0.+array if data.has_key('configuration'): box = data.get('box_size', None) if box is not None: box = box.astype(N.Float) conf = data['configuration'] data['configuration'] = \ ParticleProperties.Configuration(conf.universe, conf.array, box) return data
def test_dihedral(self): for n in [1, 2, 3, 4]: for phase in N.arange(0., 6., 0.5): for V in [-10., 2.]: self._dihedralTerm(n, phase, V)
os.unlink(filename) def _showValue(self, x, y): scale, shift = self.transformation point = N.array([x, y]) point = (point-shift)/scale self.value_label.setText(" x = %f\n y = %f" % tuple(point)) self.value_label.show() def _hideValue(self): self.value_label.hide() if __name__ == '__main__': data1 = 2.*N.pi*N.arange(200)/200. data1.shape = (100, 2) data1[:,1] = N.sin(data1[:,0]) lines1 = PolyLine(data1, color='green') pi = N.pi lines2 = PolyLine([(0., 0.), (pi/2., 1.), (pi, 0.), (3.*pi/2., -1), (2.*pi, 0.)], color='red') markers = PolyMarker([(0., 0.), (pi/2., 1.), (pi, 0.), (3.*pi/2., -1), (2.*pi, 0.)], color='blue', fillcolor='blue', marker='plus') object = PlotGraphics([lines1, lines2, markers]) def display(value):
# modes = load('~/proteins/lysozyme/lysozyme.umodes') universe = modes.universe protein = universe.protein protein.model = 'all' protein[0].model = 'all' helices = [] for chain in protein: dihedrals = chain.phiPsi()[1:-1] dihedrals_with_index = zip(range(1, 1+len(dihedrals)), dihedrals) helix_indices = [index for index, (phi, psi) in dihedrals_with_index if 4.5 < phi < 5.8 and 5. < psi < 6.] helix_indices = N.array(helix_indices) breaks = N.repeat(N.arange(len(helix_indices)-1), (helix_indices[1:]-helix_indices[:-1]) > 1) breaks = N.concatenate(([0], breaks + 1)) backbone = chain.backbone() for i in range(len(breaks)-1): residues = N.take(backbone, helix_indices[breaks[i]:breaks[i+1]]) helices.append(Collection(list(residues))) helices = [h for h in helices if len(h) > 4] #Collection(helices).view() residue_motion_vectors = [] helix_motion_vectors = [] for helix in helices: end_to_end = helix[0].centerOfMass()-helix[-1].centerOfMass() cms, inertia = helix.centerAndMomentOfInertia()