plot_averages_into_images.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #!/usr/bin/env python
  2. """
  3. This is free and unencumbered software released into the public domain.
  4. Anyone is free to copy, modify, publish, use, compile, sell, or
  5. distribute this software, either in source code form or as a compiled
  6. binary, for any purpose, commercial or non-commercial, and by any
  7. means.
  8. In jurisdictions that recognize copyright laws, the author or authors
  9. of this software dedicate any and all copyright interest in the
  10. software to the public domain. We make this dedication for the benefit
  11. of the public at large and to the detriment of our heirs and
  12. successors. We intend this dedication to be an overt act of
  13. relinquishment in perpetuity of all present and future rights to this
  14. software under copyright law.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. For more information, please refer to [http://unlicense.org]
  23. """
  24. import numpy as np
  25. import pandas as pd
  26. import matplotlib.pyplot as plt
  27. import os
  28. import sys
  29. import argparse
  30. class Options:
  31. def __init__(self):
  32. self.mcell3_dir = None
  33. self.mcell4_dir = None
  34. self.bng_dir = None
  35. self.single_bng_run = False
  36. self.labels = ['MCell4', 'MCell3R', 'NFSim']
  37. def create_argparse():
  38. parser = argparse.ArgumentParser(description='MCell4 Runner')
  39. parser.add_argument('-m4', '--mcell4', type=str, help='mcell4 react_data directory')
  40. parser.add_argument('-m3', '--mcell3', type=str, help='mcell3 react_data directory')
  41. parser.add_argument('-b', '--bng', type=str, help='bionetgen directory')
  42. parser.add_argument('-s', '--single_bng_run', action='store_true', help='the bionetgen directory contains only a single .gdat file')
  43. parser.add_argument('-l', '--labels', type=str, help='comma-separated list of labels (used in order -m4,-m3,-b')
  44. return parser
  45. def process_opts():
  46. parser = create_argparse()
  47. args = parser.parse_args()
  48. opts = Options()
  49. if args.mcell4:
  50. opts.mcell4_dir = args.mcell4
  51. if args.mcell3:
  52. opts.mcell3_dir = args.mcell3
  53. if args.bng:
  54. opts.bng_dir = args.bng
  55. if args.single_bng_run:
  56. opts.single_bng_run = args.single_bng_run
  57. if args.labels:
  58. opts.labels = args.labels.split(',')
  59. return opts
  60. def get_mcell_observables_counts(dir):
  61. counts = {}
  62. seed_dirs = os.listdir(dir)
  63. for seed_dir in seed_dirs:
  64. if not seed_dir.startswith('seed_'):
  65. continue
  66. file_list = os.listdir(os.path.join(dir, seed_dir))
  67. for file in file_list:
  68. file_path = os.path.join(dir, seed_dir, file)
  69. if os.path.isfile(file_path) and file.endswith('.dat'):
  70. observable = os.path.splitext(file)[0]
  71. if observable.endswith('_MDLString'):
  72. observable = observable[:-len('_MDLString')]
  73. if observable not in counts:
  74. index = 0
  75. else:
  76. index = counts[observable].shape[1] - 1
  77. col_name = 'count' + str(index)
  78. df = pd.read_csv(file_path, sep=' ', names=['time', col_name])
  79. if observable not in counts:
  80. counts[observable] = df
  81. else:
  82. # add new column
  83. counts[observable][col_name] = df[col_name]
  84. return counts
  85. def get_bng_observables_counts(file, counts):
  86. if not os.path.exists(file):
  87. print("Expected file " + file + " not found, skipping it")
  88. return
  89. with open(file, 'r') as f:
  90. first_line = f.readline()
  91. header = first_line.split()[1:]
  92. df = pd.read_csv(file, delim_whitespace=True, comment='#', names=header)
  93. return df
  94. def process_nsfim_gdat_file(full_dir, counts):
  95. df = get_bng_observables_counts(os.path.join(full_dir, 'test.gdat'), counts)
  96. # transform into separate dataframes based on observable
  97. for i in range(1, df.shape[1]):
  98. observable = df.columns[i]
  99. if observable not in counts:
  100. col_name = 'count0'
  101. # select time and the current observable
  102. counts[observable] = pd.DataFrame()
  103. counts[observable]['time'] = df.iloc[:, 0]
  104. counts[observable][col_name] = df.iloc[:, i]
  105. else:
  106. col_name = 'count' + str(counts[observable].shape[1] - 1)
  107. counts[observable][col_name] = df.iloc[:, i]
  108. def get_nfsim_observables_counts(opts):
  109. single_bng_run = opts.single_bng_run
  110. dir = opts.bng_dir
  111. counts = {}
  112. if not single_bng_run:
  113. nf_dirs = os.listdir(dir)
  114. for nf_dir in nf_dirs:
  115. full_dir = os.path.join(dir, nf_dir)
  116. if not nf_dir.startswith('nf_') or not os.path.isdir(full_dir):
  117. continue
  118. process_nsfim_gdat_file(full_dir, counts)
  119. else:
  120. process_nsfim_gdat_file(dir, counts)
  121. return counts
  122. def main():
  123. opts = process_opts()
  124. counts = []
  125. if opts.mcell4_dir:
  126. if os.path.exists(opts.mcell4_dir):
  127. print("Reading MCell data from " + opts.mcell4_dir)
  128. counts.append(get_mcell_observables_counts(opts.mcell4_dir))
  129. else:
  130. print("Directory " + opts.mcell4_dir + " with MCell4 data not found, ignored")
  131. sys.exit(1)
  132. else:
  133. counts.append({})
  134. if opts.mcell3_dir:
  135. if os.path.exists(opts.mcell3_dir):
  136. print("Reading MCell data from " + opts.mcell3_dir)
  137. counts.append(get_mcell_observables_counts(opts.mcell3_dir))
  138. else:
  139. print("Error: directory " + opts.mcell3_dir + " with MCell3 data not found, ignored")
  140. sys.exit(1)
  141. else:
  142. counts.append({})
  143. # get_nfsim_observables_counts may return an empty dict
  144. if opts.bng_dir:
  145. if os.path.exists(opts.bng_dir):
  146. print("Reading BNG data from " + opts.bng_dir)
  147. counts.append(get_nfsim_observables_counts(opts))
  148. else:
  149. print("Error: directory " + opts.bng_dir + " with BNG data not found, ignored")
  150. sys.exit(1)
  151. else:
  152. counts.append({})
  153. clrs = ['b', 'g', 'r']
  154. all_observables = set(counts[0].keys())
  155. all_observables = all_observables.union(set(counts[1].keys()))
  156. all_observables = all_observables.union(set(counts[2].keys()))
  157. for obs in sorted(all_observables):
  158. print("Processing observable " + obs)
  159. fig,ax = plt.subplots()
  160. ax.set_title(obs)
  161. legend_names = []
  162. for i in range(len(counts)):
  163. if obs not in counts[i]:
  164. continue
  165. data = counts[i][obs]
  166. df = pd.DataFrame()
  167. df['time'] = data.iloc[:, 0]
  168. df['means'] = data.iloc[:, 1:].mean(axis=1)
  169. print(opts.labels[i], df['means'])
  170. df['mean_minus_std'] = df['means'] - data.iloc[:, 1:].std(axis=1)
  171. df['mean_plus_std'] = df['means'] + data.iloc[:, 1:].std(axis=1)
  172. # free collected data to decrease memory consumption
  173. del data
  174. ax.plot(df['time'], df['means'], label=obs + "1", c=clrs[i])
  175. ax.fill_between(
  176. df['time'],
  177. df['mean_minus_std'], df['mean_plus_std'],
  178. alpha=0.1, facecolor=clrs[i])
  179. legend_names.append(opts.labels[i])
  180. plt.legend(legend_names)
  181. plt.xlabel("time [s]")
  182. plt.ylabel("N(t)")
  183. plt.savefig(obs + '.png', dpi=600)
  184. plt.close(fig)
  185. if __name__ == '__main__':
  186. main()