代码:
@classmethod
def analyze(cls, gmx_parser, system_dir, system_name, base_data, verbosity,
tolerance=None, dtemp=None, dpress=None):
# 检查是否定义了 温度 和 压力差
if not dtemp and not dpress:
raise ValueError('Ensemble test for system ' + system_name +
' has no defined temperature or pressure difference.')
# 补0填充和对齐
if not dtemp:
dtemp = [0] * len(dpress)
if not dpress:
dpress = [0] * len(dtemp)
if len(dtemp) < len(dpress):
dtemp.extend([0] * (len(dpress) - len(dtemp)))
if len(dpress) < len(dtemp):
dpress.extend([0] * (len(dtemp) - len(dpress)))
nsystems = len(dtemp)
if tolerance is None:
tolerance = cls.parser().get_default('tolerance')
# 基础数据
if base_data['reduced'] is None:
current_dir = os.path.join(system_dir, 'base')
base_data['reduced'] = gmx_parser.get_simulation_data(
mdp=os.path.join(current_dir, 'mdout.mdp'),
top=os.path.join(current_dir, 'system.top'),
edr=os.path.join(current_dir, 'system.edr'),
gro=os.path.join(current_dir, 'system.gro')
)
base_result = base_data['reduced']
# 生成结果列表 simulations at different state points
results = []
for n in range(nsystems):
current_dir = os.path.join(system_dir, 'ensemble_' + str(n+1))
results.append(gmx_parser.get_simulation_data(
mdp=os.path.join(current_dir, 'mdout.mdp'),
top=os.path.join(current_dir, 'system.top'),
edr=os.path.join(current_dir, 'system.edr'),
gro=os.path.join(current_dir, 'system.gro')
))
# 运行测试
passed = True
message = ''
max_quantiles = -1
for result, dt, dp in zip(results, dtemp, dpress):
quantiles = ensemble.check(base_result, result, verbosity=verbosity)
# filename=os.path.join(system_dir, system_name + '_ens'))
if any(q > tolerance or math.isnan(q) for q in quantiles):
passed = False
if len(quantiles) == 1:
message += '\n --dtemp={:.1f} --dpress={:.1f} : FAILED ({:.1f} quantiles off)'.format(
dt, dp, quantiles[0]
)
else:
message += '\n --dtemp={:.1f} --dpress={:.1f} : FAILED ([{:.1f}, {:.1f}] quantiles off)'.format(
dt, dp, quantiles[0], quantiles[1]
)
else:
if len(quantiles) == 1:
message += '\n --dtemp={:.1f} --dpress={:.1f} : PASSED ({:.1f} quantiles off)'.format(
dt, dp, quantiles[0]
)
else:
message += '\n --dtemp={:.1f} --dpress={:.1f} : PASSED ([{:.1f}, {:.1f}] quantiles off)'.format(
dt, dp, quantiles[0], quantiles[1]
)
max_quantiles = max(max_quantiles, max(quantiles))
if passed:
message = ('EnsembleTest PASSED (tolerance: {:.1f} quantiles)'.format(tolerance) +
message)
else:
message = ('EnsembleTest FAILED (tolerance: {:.1f} quantiles)'.format(tolerance) +
message)
return {'test': passed,
'result': max_quantiles,
'tolerance': tolerance,
'message': message}
这段代码定义了一个类方法"analyze",接受多个参数,包括一个解析器对象,一个目录路径,一个系统名称,一个基础数据的字典,一个详细程度,以及一些可选的与温度和压力差相关的参数。
该方法首先检查是否定义了温度或压力差,如果没有,则引发ValueError,指示该集合测试无法进行。
接下来,该方法会对温度和压力差进行处理,如果其中一个未定义,则将其补零处理。如果其中一个比另一个长度短,则用零补齐短的一个数组。处理后的温度和压力差数组长度相等。
然后,该方法获取一个tolerance值,如果未指定,则使用解析器对象的默认tolerance值。
接着,该方法获取基础数据并将其存储在一个变量中。如果基础数据中的reduced键的值为None,则获取mdp文件、top文件、edr文件和gro文件的路径,使用解析器对象获取基础数据,并将其存储在基础数据字典的reduced键中。
然后,该方法使用循环,将不同状态点的模拟数据存储在 results 列表中,并返回该列表。
运行测试部分的解释:
这段代码是一个用于测试的函数,它的作用是检查一个由三个变量(results, dtemp, dpress)组成的数据集是否满足一定的精度要求,其中results是一个包含多个数值的列表,dtemp和dpress是分别表示温度和压力的两个数值列表。函数首先对输入的数据进行迭代,对于每个数据点,它会使用ensemble.check函数检查其与一个基准结果(base_result)的相似度,并计算出一个或两个数值,表示该数据点在分位数上与基准结果的差异。如果这些差异中有任何一个大于一个指定的容忍度(tolerance),或者存在缺失值,那么该数据点被认为是失败的。在函数的执行过程中,如果有任何数据点被认为是失败的,则整个测试被认为是失败的,并且函数返回一个包含一些测试结果信息的字典。如果所有的数据点都通过了测试,则函数返回一个包含测试结果的字典。