emdbva 0.0.1.dev98__tar.gz → 0.0.1.dev101__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {emdbva-0.0.1.dev98/emdbva.egg-info → emdbva-0.0.1.dev101}/PKG-INFO +1 -1
  2. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101/emdbva.egg-info}/PKG-INFO +1 -1
  3. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/bars.py +1 -1
  4. emdbva-0.0.1.dev101/va/metrics/phaserandomization.py +174 -0
  5. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/preparation.py +9 -7
  6. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/ChimeraxViews.py +2 -1
  7. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/validationanalysis.py +27 -9
  8. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/version.py +1 -1
  9. emdbva-0.0.1.dev98/va/metrics/phaserandomization.py +0 -432
  10. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/LICENSE +0 -0
  11. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/MANIFEST.in +0 -0
  12. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/README.rst +0 -0
  13. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/emdbva.egg-info/SOURCES.txt +0 -0
  14. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/emdbva.egg-info/dependency_links.txt +0 -0
  15. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/emdbva.egg-info/entry_points.txt +0 -0
  16. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/emdbva.egg-info/requires.txt +0 -0
  17. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/emdbva.egg-info/top_level.txt +0 -0
  18. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/setup.cfg +0 -0
  19. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/setup.py +0 -0
  20. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/__init__.py +0 -0
  21. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/mainva.py +0 -0
  22. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/__init__.py +0 -0
  23. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/connected_percentage.py +0 -0
  24. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/contour_level_predicator.py +0 -0
  25. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/emda_mmcc.py +0 -0
  26. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/emringer.py +0 -0
  27. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/inclusion.py +0 -0
  28. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/phenix_cc.py +0 -0
  29. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/phenix_mm.py +0 -0
  30. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/projections.py +0 -0
  31. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/qscore.py +0 -0
  32. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/residue_locres.py +0 -0
  33. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/resmap.py +0 -0
  34. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/smoc.py +0 -0
  35. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/strudel.py +0 -0
  36. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/surfaces.py +0 -0
  37. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/metrics/threedfsc.py +0 -0
  38. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/qscores.csv +0 -0
  39. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/Checker.py +0 -0
  40. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/MapProcessor.py +0 -0
  41. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/Model.py +0 -0
  42. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/__init__.py +0 -0
  43. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/cl_weights.pth +0 -0
  44. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/log_utils.py +0 -0
  45. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/misc.py +0 -0
  46. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/rescolor.py +0 -0
  47. {emdbva-0.0.1.dev98 → emdbva-0.0.1.dev101}/va/utils/stars.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: emdbva
3
- Version: 0.0.1.dev98
3
+ Version: 0.0.1.dev101
4
4
  Summary: CryoEM validation toolkit
5
5
  Home-page: https://test.pypi.org/project/va/
6
6
  Author: Zhe Wang
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: emdbva
3
- Version: 0.0.1.dev98
3
+ Version: 0.0.1.dev101
4
4
  Summary: CryoEM validation toolkit
5
5
  Home-page: https://test.pypi.org/project/va/
6
6
  Author: Zhe Wang
@@ -81,7 +81,7 @@ def get_nearest_onethousand(new_entry, df, n, score_type):
81
81
  return df_nearest
82
82
 
83
83
 
84
- def get_resolution_range(new_entry, df, score_type, resbin=0.8):
84
+ def get_resolution_range(new_entry, df, score_type, resbin=0.5):
85
85
  """
86
86
  Sort the df based on the resolution and then find the nearest +1-1 resolution df
87
87
  """
@@ -0,0 +1,174 @@
1
+ from va.utils.ChimeraxViews import *
2
+ from va.utils.misc import find_rawmap_file
3
+ import mrcfile
4
+
5
+ def create_relion_folders(root, mapname, result_type=None):
6
+ """
7
+ Create <mapname>_relion folder in the va directory and subfolders containing mask, fsc and local_resolution
8
+ """
9
+ relion_dir = f'{root}{mapname}_relion'
10
+ mask_dir = f'{relion_dir}/mask'
11
+ fsc_dir = f'{relion_dir}/fsc'
12
+ local_resolution_dir = f'{relion_dir}/local_resolution'
13
+
14
+ if create_directory(relion_dir) and create_directory(mask_dir):
15
+ print('Relion folder and mask folder created.')
16
+ if result_type == 'fsc':
17
+ if create_directory(fsc_dir):
18
+ print('FSC folder created.')
19
+ return fsc_dir, mask_dir
20
+ else:
21
+ print('FSC folder was not created. Please check.')
22
+ return None, None
23
+
24
+ if result_type == 'locres':
25
+ if create_directory(local_resolution_dir):
26
+ print('Local resolution folder created.')
27
+ return local_resolution_dir, mask_dir
28
+ else:
29
+ print('Local resolution folder was not created. Please check.')
30
+ return None, None
31
+ print('Check the input folder type either fsc or locres.')
32
+ return None, None
33
+ else:
34
+ print('Relion folder and mask folder was not created. Please check')
35
+ return None, None
36
+
37
+
38
+ def check_mrc(input_map):
39
+ """
40
+ Check if the input map is in MRC format. If not, create a symbolic link in the same folder ends with mrc
41
+ """
42
+
43
+ suffix = '.mrc'
44
+ if not input_map.endswith('.mrc'):
45
+ last_dot_index = input_map.rfind('.')
46
+ mrc_input_map = input_map[:last_dot_index] + suffix
47
+ if create_symbolic_link(input_map, mrc_input_map):
48
+ return mrc_input_map
49
+ else:
50
+ print('MRC file format.')
51
+ return input_map
52
+
53
+ def relion_mask(raw_map, out_dir, mapname=None):
54
+ relion_mask_executable_name = 'relion_mask_create'
55
+ relion_mask_executable = find_executable(relion_mask_executable_name)
56
+ if relion_mask_executable:
57
+ original_input_mrc = check_mrc(raw_map)
58
+ angpix = get_voxel_size(raw_map)
59
+ input_mrc = mrcfile.open(original_input_mrc)
60
+ d = input_mrc.data
61
+ max_val_thirty = f'{calc_level_dev(d)[0]}'
62
+
63
+ dilatepx, softpx = calculate_pixels(angpix)
64
+ mask_loose = os.path.join(out_dir, f'{mapname}_mask.mrc')
65
+
66
+ threading_numbers = int(os.cpu_count() * 0.8)
67
+ relion_mask_cmd = (f'{relion_mask_executable} --i {original_input_mrc} --o {mask_loose} --ini_threshold '
68
+ f'{max_val_thirty} --extend_inimask {dilatepx} --width_soft_edge '
69
+ f'{softpx} --j {threading_numbers}')
70
+ print(f'Relion mask command: {relion_mask_cmd}')
71
+
72
+ if angpix and max_val_thirty and dilatepx and softpx and input_mrc:
73
+ subprocess.run(relion_mask_cmd, shell=True)
74
+ if not MapProcessor.check_map_starts(mask_loose, original_input_mrc):
75
+ print('Relion mask does not have the same nstarts as the original map.')
76
+ MapProcessor.update_map_starts(original_input_mrc, mask_loose)
77
+
78
+ return mask_loose
79
+ else:
80
+ print(f'!!! Check the cmd: {relion_mask_cmd}')
81
+ return None
82
+ else:
83
+ print('Relion mask executable is not found.')
84
+
85
+
86
+ def relion_fsc(mapone, maptwo, mask_file=None, out_dir=None):
87
+ """
88
+ Relion FSC calculation running
89
+ """
90
+ if out_dir is None:
91
+ out_dir = os.getcwd()
92
+ relion_executable_name = 'relion_postprocess'
93
+ relion_postprocess_executable = find_executable(relion_executable_name)
94
+ mapone_mrc = check_mrc(mapone)
95
+ maptwo_mrc = check_mrc(maptwo)
96
+ halfmap_exists = mapone_mrc and maptwo_mrc
97
+ if halfmap_exists and relion_postprocess_executable:
98
+ if os.path.isfile(mask_file or ''):
99
+
100
+ subprocess.run(f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc"
101
+ f" --mask {mask_file} --auto_bfac", shell=True, check=True)
102
+ print(
103
+ f'FSC cmd: {relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc '
104
+ f'--mask {mask_file} --auto_bfac", shell=True)')
105
+
106
+ return True
107
+ else:
108
+ print('No mask applied for FSC calculation.')
109
+ print(
110
+ f'!!! Check the cmd: {relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc --auto_bfac')
111
+ subprocess.run(f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc --auto_bfac",
112
+ shell=True, check=True)
113
+
114
+
115
+ return True
116
+ else:
117
+ print('Relion postprocess executable is not found or half maps missing/error.')
118
+ print(f'!!! Check the cmd: f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc '
119
+ f'--mask {mask_file} --auto_bfac", shell=True)"')
120
+ return None
121
+
122
+
123
+ def relion_fsc_calculation(mapone, maptwo, root, mapname=None):
124
+ """
125
+ Calculates FSc using Relion
126
+ return: data dictionary of fsc
127
+ """
128
+
129
+ result_type = 'fsc'
130
+ if not mapname:
131
+ mapname = f'{os.path.basename(mapone)}_{os.path.basename(maptwo)}'
132
+ fsc_dir, mask_dir = create_relion_folders(root, mapname, result_type)
133
+
134
+ try:
135
+ if fsc_dir and mask_dir:
136
+ raw_map_name = find_rawmap_file(root)
137
+ filtered_raw_map = f'{root}{raw_map_name}_lowpassed.mrc'
138
+ relion_mask_name = os.path.join(mask_dir, f'{mapname}_mask.mrc')
139
+ if not os.path.isfile(filtered_raw_map):
140
+ relion_mask_name = relion_mask(filtered_raw_map, mask_dir, mapname)
141
+ relion_fsc_result = relion_fsc(mapone, maptwo, relion_mask_name, fsc_dir)
142
+ if relion_fsc_result:
143
+ return f'{fsc_dir}/fsc.star'
144
+ else:
145
+ return None
146
+
147
+ except Exception as e:
148
+ print('No relion or fsc calculation was wrong.')
149
+ return None
150
+
151
+ def get_voxel_size(input_map):
152
+
153
+ try:
154
+ with mrcfile.open(input_map, permissive=True) as mrc:
155
+ voxel_size = mrc.voxel_size
156
+
157
+ return float(voxel_size['x'])
158
+ except Exception as e:
159
+ print('No voxel size of the map.')
160
+ return None
161
+
162
+
163
+ def calculate_pixels(angpix):
164
+ """
165
+ Calculate hard and soft pixel for mask map
166
+ """
167
+
168
+ if angpix != 0:
169
+ dilatepx = 10 / angpix
170
+ softpx = 5 / angpix
171
+ return dilatepx, softpx
172
+ else:
173
+ print('No hard and soft radius for mask as voxel value is 0.')
174
+ return None, None
@@ -426,23 +426,25 @@ class PreParation:
426
426
  # Extract map-related loops
427
427
  contour_loop = block.find_loop('_em_map.contour_level')
428
428
  file_loop = block.find_loop('_em_map.file')
429
+ map_type_loop = block.find_loop('_em_map.type')
429
430
 
430
431
  if contour_loop and file_loop:
431
432
  contour_levels = [row for row in contour_loop]
432
433
  map_files = [row for row in file_loop]
434
+ map_types = [row.replace("'","") for row in map_type_loop if "'" in row]
433
435
 
434
- for map_file, contour in zip(map_files, contour_levels):
436
+ for map_file, contour, map_type in zip(map_files, contour_levels, map_types):
435
437
  map_key = map_file[:-3] # Strip '.gz'
436
438
  contour = float(contour)
437
439
 
438
- if 'msk' in map_file:
439
- map_data['mask'] = {'mask': map_key, 'mask_contour': contour}
440
- elif 'half_map_1' in map_file:
440
+ if map_type == 'primary map':
441
+ map_data['primary'] = {'primary': map_key, 'primary_contour': contour}
442
+ if map_type =='half map' and 'half_map_1' in map_file:
441
443
  map_data['odd'] = {'odd': map_key, 'odd_contour': contour}
442
- elif 'half_map_2' in map_file:
444
+ if map_type == 'half map' and 'half_map_2' in map_file:
443
445
  map_data['even'] = {'even': map_key, 'even_contour': contour}
444
- else:
445
- map_data['primary'] = {'primary': map_key, 'primary_contour': contour}
446
+ if 'msk' in map_file:
447
+ map_data['mask'] = {'mask': map_file, 'mask_contour': contour}
446
448
 
447
449
  # Extract database cross-references
448
450
  db_ids = block.find_loop('_database_2.database_id')
@@ -572,7 +572,8 @@ class ChimeraxViews:
572
572
  'set bgColor light gray',
573
573
  ])
574
574
  mask_name = os.path.basename(mask_map)
575
- if '_relion' in mask_map and mask_map.endswith('_mask.mrc'):
575
+ # if '_relion' in mask_map and mask_map.endswith('_mask.mrc'):
576
+ if mask_map.endswith('_mask.mrc'):
576
577
  image_name = [f'{input_map_name}_{mask_name}_{axis}relionmaskview.jpeg' for axis in ['z', 'x', 'y']]
577
578
  else:
578
579
  image_name = [f'{input_map_name}_{mask_name}_{axis}maskview.jpeg' for axis in ['z', 'x', 'y']]
@@ -220,11 +220,17 @@ class ValidationAnalysis:
220
220
  self.workdir = workdir
221
221
  self.check_dir = create_directory(f'{self.workdir}/checks/')
222
222
  self.get_resolution()
223
- # self.relion_mask = self.get_relion_mask()
224
- # maskedrawmap = MapProcessor.mask_map(self.rawmap._iostream.name, self.relion_mask)
223
+ self.relion_mask = self.get_relion_mask()
224
+ # make a symbolic link for relion_mask in the va folder
225
+ if self.relion_mask:
226
+ mask_name = os.path.basename(self.relion_mask)
227
+ link_name = f'{self.workdir}/{mask_name}'
228
+ create_symbolic_link(self.relion_mask, link_name)
229
+ self.relion_mask = link_name
225
230
  # The read masked raw map here is only used in line 455 for produce the masked raw map glow image
226
- # self.masked_rawmap = mrcfile.mmap(maskedrawmap, mode='r+')
227
- # self.masked_rawmap.fullname = maskedrawmap
231
+ maskedrawmap = MapProcessor.mask_map(self.rawmap._iostream.name, self.relion_mask)
232
+ self.masked_rawmap = mrcfile.mmap(maskedrawmap, mode='r+')
233
+ self.masked_rawmap.fullname = maskedrawmap
228
234
 
229
235
 
230
236
  def get_resolution(self):
@@ -275,9 +281,10 @@ class ValidationAnalysis:
275
281
  oddmap = self.hmodd._iostream.name
276
282
  evenmap = self.hmeven._iostream.name
277
283
  try:
278
- relion_fsc_result = relion_fsc(oddmap, evenmap, None, relion_fsc_dir)
284
+ relion_fsc(oddmap, evenmap, None, relion_fsc_dir)
279
285
  except:
280
286
  print('Relion fsc calculation failed. Please check the input maps.')
287
+
281
288
  star_file_dir = f'{relion_fsc_dir}/fsc.star'
282
289
  star = GetStars(star_file_dir)
283
290
  nomask_resolution = star.final_resolution()
@@ -290,6 +297,7 @@ class ValidationAnalysis:
290
297
  print('Relion fsc and mask directories could not be created.')
291
298
  except:
292
299
  sys.stderr.write('Relion mask could not be created.')
300
+ return None
293
301
 
294
302
  # Glow LUT for color image
295
303
  def glowimage(self, im_gray):
@@ -453,7 +461,7 @@ class ValidationAnalysis:
453
461
  if self.rawmap:
454
462
  op.orthogonal_projections(self.rawmap, self.workdir, type, 'rawmap_')
455
463
  # Produce the masked raw map glow image for checking mask effect
456
- # op.orthogonal_projections(self.masked_rawmap, self.workdir, 'std')
464
+ op.orthogonal_projections(self.masked_rawmap, self.workdir, 'std')
457
465
 
458
466
  glow_std_image = f'{self.workdir}/{os.path.basename(self.rawmap.fullname)}_scaled_glow_zstd.jpeg'
459
467
  if os.path.isfile(glow_std_image):
@@ -2207,13 +2215,24 @@ class ValidationAnalysis:
2207
2215
  rawmap_cl = self.rawmapcl()
2208
2216
  viewer.new_surface_view_chimerax(rawmap_name, rawmap_cl, 'surface', 'raw')
2209
2217
 
2218
+ # Raw map and relion mask surface view
2219
+ if self.relion_mask:
2220
+ # Raw map and relion mask surface view
2221
+ raw_map_predicated_contour = MapProcessor.predict_contour(f'{rawmap_name}')
2222
+ viewer.new_surface_view_chimerax(f'{rawmap_name}', raw_map_predicated_contour, 'relionmask', '',
2223
+ self.relion_mask, 1.0)
2224
+
2210
2225
  # Primary map and model
2211
2226
  if self.models:
2212
2227
  for model in self.models:
2213
2228
  viewer.new_surface_view_chimerax(primary_input_map, primary_input_contour, 'surface', '',
2214
2229
  None, None, model.filename)
2215
2230
 
2216
- # Mask surface view
2231
+ # Relion mask surface view
2232
+ if self.relion_mask:
2233
+ viewer.new_surface_view_chimerax(self.relion_mask, 1.0, 'surface', '')
2234
+
2235
+ # Mask and primary map surface view
2217
2236
  for mask_name in self.allmasks:
2218
2237
  # Use all 1.0 for mask contour level till it is given by author in the header
2219
2238
  mask_cl = 1.0
@@ -4896,8 +4915,7 @@ class ValidationAnalysis:
4896
4915
  ylist = None
4897
4916
 
4898
4917
  try:
4899
- star_file = relion_fsc_calculation(self.hmodd.fullname, self.hmeven.fullname, self.workdir, self.mapname,
4900
- self.resolution)
4918
+ star_file = relion_fsc_calculation(self.hmodd.fullname, self.hmeven.fullname, self.workdir, self.mapname)
4901
4919
  # temporary line for get process all intersections
4902
4920
  # star_file = f'{self.workdir}/emd_{self.emdid}.map_relion/fsc/fsc.star'
4903
4921
  # star_file = '/Users/zhe/Downloads/tests/VA/nfs/msd/work2/emdb/development/staging/em/81/8117/va/emd_8117.map_relion/fsc/fsc.star'
@@ -28,4 +28,4 @@ under the License.
28
28
 
29
29
  """
30
30
 
31
- __version__ = '0.0.1.dev98'
31
+ __version__ = '0.0.1.dev101'
@@ -1,432 +0,0 @@
1
- import subprocess
2
- import timeit
3
-
4
- from va.utils.misc import *
5
- from distutils.spawn import find_executable
6
- from va.metrics.contour_level_predicator import *
7
- from va.utils.ChimeraxViews import *
8
- from va.utils.misc import find_rawmap_file
9
- import mrcfile
10
-
11
- def create_relion_folders(root, mapname, result_type=None):
12
- """
13
- Create <mapname>_relion folder in the va directory and subfolders containing mask, fsc and local_resolution
14
- """
15
- relion_dir = f'{root}{mapname}_relion'
16
- mask_dir = f'{relion_dir}/mask'
17
- fsc_dir = f'{relion_dir}/fsc'
18
- local_resolution_dir = f'{relion_dir}/local_resolution'
19
-
20
- if create_directory(relion_dir) and create_directory(mask_dir):
21
- print('Relion folder and mask folder created.')
22
- if result_type == 'fsc':
23
- if create_directory(fsc_dir):
24
- print('FSC folder created.')
25
- return fsc_dir, mask_dir
26
- else:
27
- print('FSC folder was not created. Please check.')
28
- return None, None
29
-
30
- if result_type == 'locres':
31
- if create_directory(local_resolution_dir):
32
- print('Local resolution folder created.')
33
- return local_resolution_dir, mask_dir
34
- else:
35
- print('Local resolution folder was not created. Please check.')
36
- return None, None
37
- print('Check the input folder type either fsc or locres.')
38
- return None, None
39
- else:
40
- print('Relion folder and mask folder was not created. Please check')
41
- return None, None
42
-
43
-
44
- def check_mrc(input_map):
45
- """
46
- Check if the input map is in MRC format. If not, create a symbolic link in the same folder ends with mrc
47
- """
48
-
49
- suffix = '.mrc'
50
- if not input_map.endswith('.mrc'):
51
- last_dot_index = input_map.rfind('.')
52
- mrc_input_map = input_map[:last_dot_index] + suffix
53
- if create_symbolic_link(input_map, mrc_input_map):
54
- return mrc_input_map
55
- else:
56
- print('MRC file format.')
57
- return input_map
58
-
59
- def relion_mask(raw_map, out_dir, mapname=None):
60
- relion_mask_executable_name = 'relion_mask_create'
61
- relion_mask_executable = find_executable(relion_mask_executable_name)
62
- if relion_mask_executable:
63
- original_input_mrc = check_mrc(raw_map)
64
- angpix = get_voxel_size(raw_map)
65
- input_mrc = mrcfile.open(original_input_mrc)
66
- d = input_mrc.data
67
- max_val_thirty = f'{calc_level_dev(d)[0]}'
68
-
69
- dilatepx, softpx = calculate_pixels(angpix)
70
- mask_loose = os.path.join(out_dir, f'{mapname}_mask.mrc')
71
-
72
- threading_numbers = int(os.cpu_count() * 0.8)
73
- # filter_to = 15. if float(resolution) < 8. else float(resolution) * 2.0
74
- # relion_mask_cmd = (f'{relion_mask_executable} --i {original_input_mrc} --o {mask_loose} --ini_threshold '
75
- # f'{max_val_thirty} --extend_inimask {dilatepx} --width_soft_edge '
76
- # f'{softpx} --j {threading_numbers} --lowpass {filter_to}')
77
- relion_mask_cmd = (f'{relion_mask_executable} --i {original_input_mrc} --o {mask_loose} --ini_threshold '
78
- f'{max_val_thirty} --extend_inimask {dilatepx} --width_soft_edge '
79
- f'{softpx} --j {threading_numbers}')
80
- print(f'Relion mask command: {relion_mask_cmd}')
81
-
82
- if angpix and max_val_thirty and dilatepx and softpx and input_mrc:
83
- subprocess.run(relion_mask_cmd, shell=True)
84
- if not MapProcessor.check_map_starts(mask_loose, original_input_mrc):
85
- print('Relion mask does not have the same nstarts as the original map.')
86
- MapProcessor.update_map_starts(original_input_mrc, mask_loose)
87
-
88
- return mask_loose
89
- else:
90
- print(f'!!! Check the cmd: {relion_mask_cmd}')
91
- return None
92
- else:
93
- print('Relion mask executable is not found.')
94
-
95
-
96
- def relion_fsc(mapone, maptwo, mask_file=None, out_dir=None):
97
- """
98
- Relion FSC calculation running
99
- """
100
- if out_dir is None:
101
- out_dir = os.getcwd()
102
- relion_executable_name = 'relion_postprocess'
103
- relion_postprocess_executable = find_executable(relion_executable_name)
104
- mapone_mrc = check_mrc(mapone)
105
- maptwo_mrc = check_mrc(maptwo)
106
- halfmap_exists = mapone_mrc and maptwo_mrc
107
- if halfmap_exists and relion_postprocess_executable:
108
- if os.path.isfile(mask_file or ''):
109
-
110
- subprocess.run(f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc"
111
- f" --mask {mask_file} --auto_bfac", shell=True)
112
- print(
113
- f'FSC cmd: f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc '
114
- f'--mask {mask_file} --auto_bfac", shell=True)"')
115
-
116
- return True
117
- else:
118
- print('No mask applied for FSC calculation.')
119
- print(
120
- f'!!! Check the cmd: f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir} --auto_bfac"')
121
- subprocess.run(f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir} --auto_bfac",
122
- shell=True)
123
-
124
-
125
- return True
126
- else:
127
- print('Relion postprocess executable is not found or half maps missing/error.')
128
- print(f'!!! Check the cmd: f"{relion_postprocess_executable} --i {mapone_mrc} --i2 {maptwo_mrc} --o {out_dir}/fsc '
129
- f'--mask {mask_file} --auto_bfac", shell=True)"')
130
- return None
131
-
132
-
133
- def relion_fsc_calculation(mapone, maptwo, root, mapname=None, resolution=None):
134
- """
135
- Calculates FSc using Relion
136
- return: data dictionary of fsc
137
- """
138
-
139
- result_type = 'fsc'
140
- if not mapname:
141
- mapname = f'{os.path.basename(mapone)}_{os.path.basename(maptwo)}'
142
- fsc_dir, mask_dir = create_relion_folders(root, mapname, result_type)
143
-
144
- try:
145
- if fsc_dir and mask_dir:
146
- raw_map_name = find_rawmap_file(root)
147
- filtered_raw_map = f'{root}{raw_map_name}_lowpassed.mrc'
148
- relion_mask_name = relion_mask(filtered_raw_map, mask_dir, mapname)
149
- # relion_mask_name = os.path.join(mask_dir, f'{mapname}_mask.mrc')
150
- # relion_mask_name = relion_mask(f'{root}{raw_map_name}', mask_dir, relion_mask_executable, mapname, resolution)
151
- # Generate Relion mask view with raw map at predicated contour level
152
- raw_map_predicated_contour = MapProcessor.predict_contour(f'{root}{raw_map_name}')
153
- viewer = ChimeraxViews(va_dir=root)
154
- viewer.new_surface_view_chimerax(f'{root}{raw_map_name}', raw_map_predicated_contour, 'relionmask', '', relion_mask_name, 1.0)
155
- relion_fsc_result = relion_fsc(mapone, maptwo, relion_mask_name, fsc_dir)
156
- if relion_fsc_result:
157
- return f'{fsc_dir}/fsc.star'
158
- else:
159
- return None
160
-
161
- except Exception as e:
162
- print('No relion or fsc calculation was wrong.')
163
- return None
164
-
165
- def get_voxel_size(input_map):
166
-
167
- try:
168
- with mrcfile.open(input_map, permissive=True) as mrc:
169
- voxel_size = mrc.voxel_size
170
-
171
- return float(voxel_size['x'])
172
- except Exception as e:
173
- print('No voxel size of the map.')
174
- return None
175
-
176
-
177
- def calculate_pixels(angpix):
178
- """
179
- Calculate hard and soft pixel for mask map
180
- """
181
-
182
- if angpix != 0:
183
- dilatepx = 10 / angpix
184
- softpx = 5 / angpix
185
- return dilatepx, softpx
186
- else:
187
- print('No hard and soft radius for mask as voxel value is 0.')
188
- return None, None
189
-
190
-
191
- # def read_fscs(star):
192
- # # Read the block, note data_fsc becomes fsc
193
- # fsc_block = cif.read_file(str(star)).find_block("fsc")
194
- #
195
- # # Read the loop, note loop_ excluded and only search by suffix
196
- # resolution = list(fsc_block.find_loop("_rlnResolution"))
197
- # resolutionAng = list(fsc_block.find_loop("_rlnAngstromResolution"))
198
- # fsc = list(fsc_block.find_loop("_rlnFourierShellCorrelationCorrected"))
199
- # fsc_unmasked = list(fsc_block.find_loop("_rlnFourierShellCorrelationUnmaskedMaps"))
200
- # fsc_randomised = list(fsc_block.find_loop("_rlnCorrectedFourierShellCorrelationPhaseRandomizedMaskedMaps"))
201
- #
202
- # # Create a DataFrame for the fsc values
203
- # data = {
204
- # 'resolution': pd.Series(resolution, dtype=float),
205
- # 'resolutionAng': pd.Series(resolutionAng, dtype=float),
206
- # 'fsc_corrected': pd.Series(fsc, dtype=float),
207
- # 'fsc_unmasked': pd.Series(fsc_unmasked, dtype=float),
208
- # 'fsc_randomised': pd.Series(fsc_randomised, dtype=float)
209
- # }
210
- # df = pd.DataFrame(data)
211
- #
212
- # return df
213
-
214
- # def assess_fscs(star, df):
215
- # print('Assessing post processing star file')
216
- # ## Postprocessing information
217
- # # Read the block, note data_
218
- # block = cif.read_file(star).find_block("general")
219
- #
220
- # # Read star file pairs, excluded and only search by suffix
221
- # randomise = block.find_pair("_rlnRandomiseFrom")[1]
222
- #
223
- # bfac = block.find_pair("_rlnBfactorUsedForSharpening")[1]
224
- #
225
- # # Look up the 'resolution' value corresponding to the 'randomise' value in df
226
- # resolution_randomise = df[df['resolutionAng'] == float(randomise)]['resolution'].values
227
- #
228
- # # Check if the resolution corresponding to randomise value is found in df
229
- # if resolution_randomise:
230
- # resolution_randomise = resolution_randomise[0]
231
- # else:
232
- # resolution_randomise = 0
233
- #
234
- # ## Do some sanity checks on the FSC curves
235
- # # Report
236
- # print()
237
- # print('### Phase randomisation assessment:')
238
- # print()
239
- # print(f"The resolution (Ang) value where phases were randomised is: {randomise}")
240
- # print(f"The corresponding resolution value is: {resolution_randomise}")
241
- # print()
242
- #
243
- # # Filter the DataFrame for FSC_randomised values below 0.143
244
- # filtered_df = df[df['fsc_randomised'] < 0.143]
245
- # # Check if there are rows in the filtered DataFrame
246
- # if not filtered_df.empty:
247
- # randomisation_drop = 'normal behaviour'
248
- # # Retrieve the resolution value when FSC drops below 0.143
249
- # resolutionAng_rdm_below_0_143 = filtered_df.iloc[0]['resolutionAng']
250
- # resolution_rdm_below_0_143 = filtered_df.iloc[0]['resolution']
251
- # print(f"The resolution (Ang) value where FSC_randomised drops below 0.143 is: {resolutionAng_rdm_below_0_143}")
252
- # print(f"The corresponding resolution value is: {resolution_rdm_below_0_143}")
253
- # print()
254
- #
255
- # # Is the rate of drop from phase randomisation rapid?
256
- # differenceAng = float(randomise) - float(resolutionAng_rdm_below_0_143)
257
- # difference = float(resolution_rdm_below_0_143) - float(resolution_randomise)
258
- # print(f"The FSC_randomisation drops from 1-0.143 in x (Ang): {differenceAng}")
259
- # print(f"The FSC_randomisation drops from 1-0.143 in x (1/Ang): {difference}")
260
- # print('Low values are better, indicating a rapid drop in the phase randomised curve after phase randomisation')
261
- # print()
262
- # # This is an example check and needs validating to establish what the correct normal and abnormal behaviour is
263
- # if difference > 0.05:
264
- # randomisation_rate = 'abnormal behaviour'
265
- # else:
266
- # randomisation_rate = 'normal behaviour'
267
- #
268
- # else:
269
- # randomisation_rate = 'N.D.'
270
- # randomisation_drop = 'abnormal behaviour'
271
- #
272
- # # Phase randomisation reporting
273
- # print('1: FSC_randomised drops below 0.143: '+randomisation_drop)
274
- # print('2: FSC_randomised drop rate from 1-0.143: '+randomisation_rate)
275
- #
276
- # print()
277
- # print('### Resolution assessment:')
278
- # print()
279
- #
280
- # measure_resolution(df, 0.143, 'fsc_randomised', 'FSC_randomised')
281
- # measure_resolution(df, 0.143, 'fsc_unmasked', 'FSC_unmasked')
282
- # measure_resolution(df, 0.143, 'fsc_corrected', 'FSC_masked_corrected')
283
- #
284
- # print()
285
- #
286
- # # Declare naughty global variables
287
- # assess_fscs.bfac = bfac
288
-
289
- # def measure_resolution(df, threshold, column, label):
290
- # # Filter the DataFrame for FSC values below 0.143
291
- # filtered_df = df[df[column] < threshold]
292
- # # Retrieve the resolution value when FSC drops below 0.143
293
- # resolution_below_0_143 = filtered_df.iloc[0]['resolutionAng']
294
- #
295
- # print(f"The resolution (Ang) value where FSC drops below "+str(threshold)+" for "+str(label)+": "+str(resolution_below_0_143))
296
-
297
-
298
- # def generate_mask(mapname, mapone, maptwo, out_dir):
299
- #
300
- # angpix = get_voxel_size(mapone)
301
- # dilatepx, softpx = calculate_pixels(angpix)
302
- #
303
- # output_directory = os.path.join(out_dir, f'{mapname}_relion_phrand')
304
- # mask_loose = os.path.join(output_directory, f'{mapname}_mask_loose.mrc')
305
- # os.makedirs(output_directory, exist_ok=True)
306
- #
307
- # if not os.path.isfile(mask_loose):
308
- # output = subprocess.run(f"relion_image_handler --i {mapone} --stats", shell=True, capture_output=True,
309
- # text=True)
310
- # mapvalmax = output.stdout.split('=')[5].split(';')[0]
311
- #
312
- # mapval25 = float(mapvalmax) * 0.30
313
- # mapval25_formatted = f"{mapval25:.3f}"
314
- #
315
- # print(f"The 30% of mapvalmax is: {mapval25_formatted}")
316
- #
317
- # subprocess.run(
318
- # f"relion_mask_create --i {mapone} --o {mask_loose} --ini_threshold {mapval25_formatted} --extend_inimask {dilatepx} --width_soft_edge {softpx}",
319
- # shell=True)
320
- #
321
- # return mask_loose
322
- # else:
323
- # print("mask_loose.mrc already exists. Skipping mask creation.")
324
- # return None
325
-
326
-
327
- # def generate_star(mapname, mapone, maptwo, out_dir):
328
- #
329
- # mask_loose = generate_mask(mapname, mapone, out_dir)
330
- # postprocess_star_file = os.path.join(out_dir, f'{mapname}_postprocess.star')
331
- # if not os.path.isfile(postprocess_star_file) and os.path.isfile(mask_loose):
332
- # subprocess.run(f"relion_postprocess --i {mapone} --i2 {maptwo} --o {out_dir}/{mapname}_relion_phrand --mask {mask_loose} --auto_bfac",
333
- # shell=True)
334
- # else:
335
- # print("postprocess.star already exists. Skipping post-processing.")
336
- #
337
- #
338
- # if os.path.isfile(postprocess_star_file):
339
- # return postprocess_star_file
340
- # else:
341
- # return None
342
-
343
- # def create_mrclink(mapone, maptwo):
344
- #
345
- # cmapone = mapone[:-2] + 'rc'
346
- # cmaptwo = maptwo[:-2] + 'rc'
347
- # if not os.path.isfile(cmapone):
348
- # create_symbolic_link(mapone, cmapone)
349
- # if not os.path.isfile(cmaptwo):
350
- # create_symbolic_link(maptwo, cmaptwo)
351
- #
352
- # return cmapone, cmaptwo
353
- #
354
-
355
- # def plot_fsc(df, plt_name):
356
- # # Set the style to whitegrid
357
- # plt.style.use('seaborn-whitegrid')
358
- #
359
- # # Create a figure and axis objects
360
- # fig, ax = plt.subplots(figsize=(10, 6))
361
- #
362
- # # Plot scatter plots
363
- # ax.scatter(df["resolution"], df["fsc_corrected"], label="FSC_masked_corrected", color='blue')
364
- # ax.scatter(df["resolution"], df["fsc_unmasked"], label="FSC_unmasked", color='grey')
365
- # ax.scatter(df["resolution"], df["fsc_randomised"], label="FSC Randomised", color='orange')
366
- #
367
- # # Plot line plots
368
- # ax.plot(df["resolution"], df["fsc_corrected"], color='blue')
369
- # ax.plot(df["resolution"], df["fsc_unmasked"], color='grey')
370
- # ax.plot(df["resolution"], df["fsc_randomised"], color='orange')
371
- #
372
- # # Add a horizontal line at FSC value 0.143
373
- # ax.axhline(y=0.143, color='red', linestyle='--', label='FSC = 0.143')
374
- #
375
- # # Set title and labels
376
- # ax.set_title('FSC Corrected')
377
- # ax.set_xlabel('Resolution (1/Ang)')
378
- # ax.set_ylabel('FSC Values')
379
- #
380
- # # Add legend
381
- # ax.legend()
382
- #
383
- # # Save the plot
384
- # plt.savefig(plt_name)
385
-
386
-
387
-
388
- # def plot_fsc(df, plt_name):
389
- # ## Plotting the scatter plot with lines
390
- # sns.set(style="whitegrid")
391
- #
392
- # plt.figure(figsize=(10, 6))
393
- #
394
- # sns.scatterplot(data=df, x="resolution", y="fsc_corrected", label="FSC_masked_corrected", color='blue')
395
- # sns.scatterplot(data=df, x="resolution", y="fsc_unmasked", label="FSC_unmasked", color='grey')
396
- # sns.scatterplot(data=df, x="resolution", y="fsc_randomised", label="FSC Randomised", color='orange')
397
- #
398
- # sns.lineplot(data=df, x="resolution", y="fsc_corrected", color='blue')
399
- # sns.lineplot(data=df, x="resolution", y="fsc_unmasked", color='grey')
400
- # sns.lineplot(data=df, x="resolution", y="fsc_randomised", color='orange')
401
- #
402
- # # Add a horizontal line at FSC value 0.143
403
- # plt.axhline(y=0.143, color='red', linestyle='--', label='FSC = 0.143')
404
- #
405
- # plt.title('FSC Corrected')
406
- # plt.xlabel('Resolution (1/Ang)')
407
- # plt.ylabel('FSC Values')
408
- #
409
- # plt.legend()
410
- # plt.savefig(plt_name)
411
- # def post_phrand(mapname, mapone, maptwo, out_dir):
412
- #
413
- # onemrc, twomrc = create_mrclink(mapone, maptwo)
414
- # ## Define the relion postprocess.star file for assessment
415
- # star = generate_star(mapname, onemrc, twomrc, out_dir)
416
- #
417
- # ## Read FSC values into dataframe
418
- # if star:
419
- # df = read_fscs(star)
420
- #
421
- # ## Do FSC curve assessments
422
- # assess_fscs(star, df)
423
- #
424
- # # Check if the postprocess.star file already exists
425
- # if not star:
426
- # subprocess.run(f"relion_postprocess --i {input_file1} --i2 {input_file2} --o {output_directory}/postprocess --mask {mask_loose} --adhoc_bfac {assess_fscs.bfac} --locres", shell=True)
427
- # else:
428
- # print("postprocess.star already exists. Skipping post-processing.")
429
- #
430
- # ## plot FSC curves
431
- # plot_name = f'{out_dir}/{mapname}_relion_fsc.png'
432
- # plot_fsc(df, plot_name)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes