emdbva 0.0.1.dev145__tar.gz → 0.0.1.dev147__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.
- {emdbva-0.0.1.dev145/emdbva.egg-info → emdbva-0.0.1.dev147}/PKG-INFO +1 -1
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147/emdbva.egg-info}/PKG-INFO +1 -1
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/resmap.py +7 -7
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/prepareandrun_codon_airflow.py +78 -84
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/misc.py +63 -37
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/stars.py +373 -93
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/validationanalysis.py +24 -13
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/version.py +1 -1
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/LICENSE +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/MANIFEST.in +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/README.rst +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/emdbva.egg-info/SOURCES.txt +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/emdbva.egg-info/dependency_links.txt +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/emdbva.egg-info/entry_points.txt +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/emdbva.egg-info/requires.txt +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/emdbva.egg-info/top_level.txt +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/setup.cfg +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/setup.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/PATHS_codon_airflow.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/__init__.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/audit/__init__.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/audit/cif_revision.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/mainva.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/__init__.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/bars.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/connected_percentage.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/contour_level_predicator.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/emda_mmcc.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/emringer.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/inclusion.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/map_data_validation.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/overlap_percentage.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/phaserandomization.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/phenix_cc.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/phenix_mm.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/projections.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/qscore.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/residue_locres.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/smoc.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/strudel.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/surfaces.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/metrics/threedfsc.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/preparation.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/qscores.csv +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/schemas/__init__.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/schemas/emdb_entry_full.schema.json +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/schemas/loader.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/Checker.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/ChimeraxViews.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/MapProcessor.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/Model.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/__init__.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/cl_weights.pth +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/log_utils.py +0 -0
- {emdbva-0.0.1.dev145 → emdbva-0.0.1.dev147}/va/utils/rescolor.py +0 -0
|
@@ -180,7 +180,7 @@ def resmap_filecheck(mapone, output_path):
|
|
|
180
180
|
return check if check else False
|
|
181
181
|
|
|
182
182
|
|
|
183
|
-
def
|
|
183
|
+
def relion_local_res_chimerax(orgmap, mapone, output_path):
|
|
184
184
|
"""
|
|
185
185
|
Generate chimerax cmd for ResMap results
|
|
186
186
|
|
|
@@ -188,10 +188,10 @@ def resmap_chimerax(mapone, output_path):
|
|
|
188
188
|
None. ChimeraX command files may be written to the output directory.
|
|
189
189
|
"""
|
|
190
190
|
|
|
191
|
-
mapname = os.path.basename(mapone)
|
|
192
191
|
output_chimerax_file = '{}{}_chimerax.cxc'.format(output_path, os.path.basename(mapone))
|
|
193
|
-
orgmap =
|
|
194
|
-
resmap = '{}{}_ori_resmap.map'.format(output_path, os.path.splitext(mapname)[0])
|
|
192
|
+
orgmap = orgmap
|
|
193
|
+
# resmap = '{}{}_ori_resmap.map'.format(output_path, os.path.splitext(mapname)[0])
|
|
194
|
+
resmap = mapone
|
|
195
195
|
header = mrcfile.open(mapone, mode='r', header_only=True)
|
|
196
196
|
voxsizes = header.voxel_size.tolist()
|
|
197
197
|
if all(element == voxsizes[0] for element in voxsizes):
|
|
@@ -305,12 +305,12 @@ def run_resmap_chimerax(bindisplay, locCHIMERA, cxcfile):
|
|
|
305
305
|
if not bindisplay:
|
|
306
306
|
subprocess.check_call(locCHIMERA + " --offscreen --nogui " + cxcfile, cwd=os.path.dirname(cxcfile),
|
|
307
307
|
shell=True)
|
|
308
|
-
print('Animated PNG for
|
|
308
|
+
print('Animated PNG for local resolution result has been produced.')
|
|
309
309
|
else:
|
|
310
310
|
subprocess.check_call(locCHIMERA + " " + cxcfile, cwd=os.path.dirname(cxcfile), shell=True)
|
|
311
|
-
print('Animated PNG for
|
|
311
|
+
print('Animated PNG for local resolution result has been produced.')
|
|
312
312
|
except subprocess.CalledProcessError as suberr:
|
|
313
|
-
err = 'Saving
|
|
313
|
+
err = 'Saving local resolution animated png error: {}.'.format(suberr)
|
|
314
314
|
errlist.append(err)
|
|
315
315
|
sys.stderr.write(err + '\n')
|
|
316
316
|
|
|
@@ -627,7 +627,14 @@ class prepareandrun():
|
|
|
627
627
|
logging.info('Validation command completed.')
|
|
628
628
|
self.data_sync()
|
|
629
629
|
else:
|
|
630
|
-
logging.
|
|
630
|
+
logging.error(
|
|
631
|
+
'Validation command failed with exit code %s; skipping data sync. '
|
|
632
|
+
'See stdout: %s and stderr: %s',
|
|
633
|
+
return_code,
|
|
634
|
+
stdout_path,
|
|
635
|
+
stderr_path,
|
|
636
|
+
)
|
|
637
|
+
raise subprocess.CalledProcessError(return_code, orgcmd)
|
|
631
638
|
|
|
632
639
|
# predmem = self.memmsg(self.mapsize)
|
|
633
640
|
# bsub -M predmem .....
|
|
@@ -665,7 +672,7 @@ class prepareandrun():
|
|
|
665
672
|
|
|
666
673
|
def data_sync(self):
|
|
667
674
|
"""
|
|
668
|
-
sync data at corresponding folder to
|
|
675
|
+
sync data at corresponding folder to public production folders
|
|
669
676
|
|
|
670
677
|
:return: None
|
|
671
678
|
"""
|
|
@@ -673,94 +680,82 @@ class prepareandrun():
|
|
|
673
680
|
result_folder = '{}{}/va/'.format(MAP_SERVER_PATH, sub_dir)
|
|
674
681
|
id = list(self.idsubdirs.keys())[0]
|
|
675
682
|
prod_folder = '{}/{}/va'.format(VA_PROD_PATH, sub_dir)
|
|
683
|
+
fallback_prod_folder = prod_folder.replace('/nfs/public/', '/nfs/ebi/public/', 1)
|
|
676
684
|
logging.info(prod_folder)
|
|
685
|
+
logging.info(fallback_prod_folder)
|
|
677
686
|
alljsonfile = glob.glob('{}emd_{}_all.json'.format(result_folder, id))
|
|
678
|
-
if alljsonfile:
|
|
687
|
+
if not alljsonfile:
|
|
688
|
+
logging.info('No all json output, job failed to the end')
|
|
689
|
+
return None
|
|
690
|
+
|
|
691
|
+
rsync_filters = (
|
|
692
|
+
"--include '*/' "
|
|
693
|
+
"--include '*_rawmap.map' "
|
|
694
|
+
"--include '*_mask.mrc' "
|
|
695
|
+
"--exclude '*_locres.mrc' "
|
|
696
|
+
"--exclude '*.map' "
|
|
697
|
+
"--exclude '*.mrc' "
|
|
698
|
+
"--exclude '*.gz' "
|
|
699
|
+
"--exclude 'emd-*.cif' "
|
|
700
|
+
"--include '*' "
|
|
701
|
+
)
|
|
702
|
+
|
|
703
|
+
def sync_command(target_folder):
|
|
679
704
|
quoted_result = shlex.quote(result_folder)
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
"--exclude '*.mrc' "
|
|
689
|
-
"--exclude '*.gz' "
|
|
690
|
-
"--exclude 'emd-*.cif' "
|
|
691
|
-
"--include '*' "
|
|
705
|
+
quoted_target = shlex.quote(target_folder.rstrip('/'))
|
|
706
|
+
return (
|
|
707
|
+
'mkdir -p {target} && '
|
|
708
|
+
'rsync -avzrhP {filters}{source} {target}/'
|
|
709
|
+
).format(
|
|
710
|
+
target=quoted_target,
|
|
711
|
+
filters=rsync_filters,
|
|
712
|
+
source=quoted_result,
|
|
692
713
|
)
|
|
693
714
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
715
|
+
def sbatch_command(job_name, stdout_name, stderr_name, target_folder):
|
|
716
|
+
wrap_cmd = sync_command(target_folder)
|
|
717
|
+
return (
|
|
718
|
+
'sbatch --wait -p datamover --mem=10G --time 12:00:00 '
|
|
719
|
+
'-J {job_name} --mail-user=pdb_em@ebi.ac.uk '
|
|
720
|
+
'--mail-type=END --mail-type=FAIL '
|
|
721
|
+
'-o {stdout_path} -e {stderr_path} --wrap="{wrap_cmd}"'
|
|
722
|
+
).format(
|
|
723
|
+
job_name=shlex.quote(job_name),
|
|
724
|
+
stdout_path=shlex.quote('{}{}'.format(result_folder, stdout_name)),
|
|
725
|
+
stderr_path=shlex.quote('{}{}'.format(result_folder, stderr_name)),
|
|
726
|
+
wrap_cmd=wrap_cmd,
|
|
697
727
|
)
|
|
698
|
-
prod_stdout = f"{result_folder}{id}_prodsync_stdout.txt"
|
|
699
|
-
prod_stderr = f"{result_folder}{id}_prodsync_stderr.txt"
|
|
700
|
-
|
|
701
|
-
# for codon staging, production and dev
|
|
702
|
-
try:
|
|
703
|
-
subprocess.check_call(['ssh', 'wp-p1m2-e1',
|
|
704
|
-
'ls ' + prod_folder],
|
|
705
|
-
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
706
|
-
prod_rc = self.run_shell_command(sync_cmd, prod_stdout, prod_stderr)
|
|
707
|
-
if prod_rc == 0:
|
|
708
|
-
logging.info('Target folder exists and data sync to production has completed')
|
|
709
|
-
else:
|
|
710
|
-
logging.info('Target folder exists but data sync to production failed')
|
|
711
|
-
|
|
712
|
-
# sync data to HL
|
|
713
|
-
fallback_prod_folder = prod_folder
|
|
714
|
-
quoted_fallback_prod_folder = shlex.quote(fallback_prod_folder)
|
|
715
|
-
quoted_fallback_source = shlex.quote(fallback_prod_folder.rstrip('/') + '/')
|
|
716
|
-
quoted_fallback_dest = 'hl2-ws-login:' + shlex.quote(fallback_prod_folder.rstrip('/') + '/')
|
|
717
|
-
|
|
718
|
-
fallback_sync_cmd = (
|
|
719
|
-
f"ssh hl2-ws-login 'mkdir -p {quoted_fallback_prod_folder}' && "
|
|
720
|
-
f"rsync -avzrhP {rsync_filters}"
|
|
721
|
-
f"{quoted_fallback_source} {quoted_fallback_dest}"
|
|
722
|
-
)
|
|
723
|
-
fallback_stdout = f"{result_folder}{id}_fallbacksync_stdout.txt"
|
|
724
|
-
fallback_stderr = f"{result_folder}{id}_fallbacksync_stderr.txt"
|
|
725
|
-
fallback_rc = self.run_shell_command(fallback_sync_cmd, fallback_stdout, fallback_stderr)
|
|
726
|
-
if fallback_rc == 0:
|
|
727
|
-
logging.info("Fallback validation_analysis sync has completed")
|
|
728
|
-
else:
|
|
729
|
-
logging.info("Fallback validation_analysis sync failed")
|
|
730
728
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
logging.info('Target folder not properly produced.')
|
|
762
|
-
else:
|
|
763
|
-
logging.info('No all json output, job failed to the end')
|
|
729
|
+
sync_jobs = [
|
|
730
|
+
(
|
|
731
|
+
'production',
|
|
732
|
+
sbatch_command(
|
|
733
|
+
'vasync_{}'.format(id),
|
|
734
|
+
'{}_prodsync_stdout.txt'.format(id),
|
|
735
|
+
'{}_prodsync_stderr.txt'.format(id),
|
|
736
|
+
prod_folder,
|
|
737
|
+
),
|
|
738
|
+
),
|
|
739
|
+
(
|
|
740
|
+
'fallback',
|
|
741
|
+
sbatch_command(
|
|
742
|
+
'vafallbacksync_{}'.format(id),
|
|
743
|
+
'{}_fallbacksync_stdout.txt'.format(id),
|
|
744
|
+
'{}_fallbacksync_stderr.txt'.format(id),
|
|
745
|
+
fallback_prod_folder,
|
|
746
|
+
),
|
|
747
|
+
),
|
|
748
|
+
]
|
|
749
|
+
|
|
750
|
+
for label, job_cmd in sync_jobs:
|
|
751
|
+
logging.info('Submitting %s sync job...', label)
|
|
752
|
+
logging.info(job_cmd)
|
|
753
|
+
subprocess.check_call(
|
|
754
|
+
['ssh', 'codon-slurm-login', job_cmd],
|
|
755
|
+
stdout=subprocess.PIPE,
|
|
756
|
+
stderr=subprocess.PIPE,
|
|
757
|
+
)
|
|
758
|
+
logging.info('%s sync job has been submitted', label)
|
|
764
759
|
|
|
765
760
|
return None
|
|
766
761
|
|
|
@@ -1069,7 +1064,6 @@ def main():
|
|
|
1069
1064
|
|
|
1070
1065
|
if not myobj.onlycopy and not myobj.onlysync:
|
|
1071
1066
|
myobj.runcmd()
|
|
1072
|
-
myobj.data_sync()
|
|
1073
1067
|
else:
|
|
1074
1068
|
logging.info('Only copy files. Please make sure use --update t/Ture/1')
|
|
1075
1069
|
|
|
@@ -142,51 +142,74 @@ def interpolated_intercept(x, y1, y2):
|
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
def interpolated_intercepts_general(x, y1, y2):
|
|
145
|
-
"""
|
|
145
|
+
"""
|
|
146
|
+
Find intersections between two curves sharing the same x-axis.
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
This version avoids nan/inf intersections and avoids divide-by-zero
|
|
149
|
+
from the general line-intersection method.
|
|
150
|
+
"""
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
x = np.asarray(x, dtype=float)
|
|
153
|
+
y1 = np.asarray(y1, dtype=float)
|
|
154
|
+
y2 = np.asarray(y2, dtype=float)
|
|
153
155
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
min_len = min(len(x), len(y1), len(y2))
|
|
157
|
+
x = x[:min_len]
|
|
158
|
+
y1 = y1[:min_len]
|
|
159
|
+
y2 = y2[:min_len]
|
|
156
160
|
|
|
157
|
-
|
|
158
|
-
A = (p1[1] - p2[1])
|
|
159
|
-
B = (p2[0] - p1[0])
|
|
160
|
-
C = (p1[0] * p2[1] - p2[0] * p1[1])
|
|
161
|
-
return A, B, -C
|
|
161
|
+
valid = np.isfinite(x) & np.isfinite(y1) & np.isfinite(y2)
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Dy = L1[0] * L2[2] - L1[2] * L2[0]
|
|
167
|
-
x = Dx / D
|
|
168
|
-
y = Dy / D
|
|
169
|
-
return x, y
|
|
170
|
-
|
|
171
|
-
L1 = line([point1[0], point1[1]], [point2[0], point2[1]])
|
|
172
|
-
L2 = line([point3[0], point3[1]], [point4[0], point4[1]])
|
|
163
|
+
x = x[valid]
|
|
164
|
+
y1 = y1[valid]
|
|
165
|
+
y2 = y2[valid]
|
|
173
166
|
|
|
174
|
-
|
|
167
|
+
if len(x) < 2:
|
|
168
|
+
return [], []
|
|
175
169
|
|
|
176
|
-
|
|
170
|
+
order = np.argsort(x)
|
|
171
|
+
x = x[order]
|
|
172
|
+
y1 = y1[order]
|
|
173
|
+
y2 = y2[order]
|
|
177
174
|
|
|
175
|
+
diff = y1 - y2
|
|
178
176
|
|
|
179
177
|
xcs = []
|
|
180
178
|
ycs = []
|
|
181
179
|
|
|
182
|
-
for
|
|
183
|
-
|
|
180
|
+
for i in range(len(x) - 1):
|
|
181
|
+
x0 = x[i]
|
|
182
|
+
x1 = x[i + 1]
|
|
183
|
+
d0 = diff[i]
|
|
184
|
+
d1 = diff[i + 1]
|
|
185
|
+
|
|
186
|
+
if not np.isfinite(d0) or not np.isfinite(d1):
|
|
187
|
+
continue
|
|
188
|
+
|
|
189
|
+
if x1 == x0:
|
|
190
|
+
continue
|
|
191
|
+
|
|
192
|
+
# Exact crossing at the first point.
|
|
193
|
+
if d0 == 0:
|
|
194
|
+
xc = x0
|
|
195
|
+
yc = y1[i]
|
|
184
196
|
|
|
185
|
-
|
|
186
|
-
|
|
197
|
+
# Crossing between two adjacent points.
|
|
198
|
+
elif d0 * d1 < 0:
|
|
199
|
+
denom = d0 - d1
|
|
200
|
+
if denom == 0:
|
|
201
|
+
continue
|
|
202
|
+
|
|
203
|
+
t = d0 / denom
|
|
204
|
+
xc = x0 + t * (x1 - x0)
|
|
205
|
+
yc = y1[i] + t * (y1[i + 1] - y1[i])
|
|
206
|
+
|
|
207
|
+
else:
|
|
208
|
+
continue
|
|
187
209
|
|
|
188
|
-
|
|
189
|
-
|
|
210
|
+
if np.isfinite(xc) and np.isfinite(yc):
|
|
211
|
+
xcs.append(float(xc))
|
|
212
|
+
ycs.append(float(yc))
|
|
190
213
|
|
|
191
214
|
return xcs, ycs
|
|
192
215
|
|
|
@@ -198,12 +221,15 @@ def remove_duplicate_intersections(xs, ys):
|
|
|
198
221
|
:param ys: list of y values
|
|
199
222
|
"""
|
|
200
223
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
224
|
+
pairs = []
|
|
225
|
+
|
|
226
|
+
for x, y in zip(xs, ys):
|
|
227
|
+
if not np.isfinite(x) or not np.isfinite(y):
|
|
228
|
+
continue
|
|
229
|
+
|
|
230
|
+
pairs.append((round(float(x), 5), round(float(y), 5)))
|
|
231
|
+
|
|
232
|
+
unique_pairs_list = sorted(set(pairs), key=lambda pair: pair[0])
|
|
207
233
|
|
|
208
234
|
return unique_pairs_list
|
|
209
235
|
|
|
@@ -335,31 +335,61 @@ class GetStars:
|
|
|
335
335
|
|
|
336
336
|
return final_curves
|
|
337
337
|
|
|
338
|
-
|
|
339
338
|
@staticmethod
|
|
340
339
|
def intersections_into_curve(intersections, levels, corrected_curve, phase_rand_curve):
|
|
341
340
|
"""
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
:param intersections: list of data pairs containing intersections
|
|
345
|
-
:param levels: list of x value of two intersect curves
|
|
346
|
-
:param corrected_curve: list of value of correction curve correlation values
|
|
347
|
-
:param phase_rand_curve: list of value of phase rand curve correlation
|
|
341
|
+
Insert valid intersection x-values into the curve x-axis and interpolate
|
|
342
|
+
corrected and phase-randomized curves onto the new x-axis.
|
|
348
343
|
"""
|
|
349
344
|
|
|
350
|
-
|
|
345
|
+
levels = np.asarray(levels, dtype=float)
|
|
346
|
+
corrected_curve = np.asarray(corrected_curve, dtype=float)
|
|
347
|
+
phase_rand_curve = np.asarray(phase_rand_curve, dtype=float)
|
|
351
348
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
349
|
+
valid = (
|
|
350
|
+
np.isfinite(levels)
|
|
351
|
+
& np.isfinite(corrected_curve)
|
|
352
|
+
& np.isfinite(phase_rand_curve)
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
levels = levels[valid]
|
|
356
|
+
corrected_curve = corrected_curve[valid]
|
|
357
|
+
phase_rand_curve = phase_rand_curve[valid]
|
|
358
|
+
|
|
359
|
+
if len(levels) < 2:
|
|
360
|
+
return levels, corrected_curve, phase_rand_curve
|
|
361
|
+
|
|
362
|
+
order = np.argsort(levels)
|
|
363
|
+
levels = levels[order]
|
|
364
|
+
corrected_curve = corrected_curve[order]
|
|
365
|
+
phase_rand_curve = phase_rand_curve[order]
|
|
366
|
+
|
|
367
|
+
# Remove duplicated x values because np.interp needs increasing x.
|
|
368
|
+
unique_levels, unique_idx = np.unique(levels, return_index=True)
|
|
369
|
+
levels = unique_levels
|
|
370
|
+
corrected_curve = corrected_curve[unique_idx]
|
|
371
|
+
phase_rand_curve = phase_rand_curve[unique_idx]
|
|
372
|
+
|
|
373
|
+
intersection_xs = []
|
|
374
|
+
|
|
375
|
+
for x, y in intersections:
|
|
376
|
+
if not np.isfinite(x) or not np.isfinite(y):
|
|
377
|
+
continue
|
|
361
378
|
|
|
362
|
-
|
|
379
|
+
if levels[0] <= x <= levels[-1]:
|
|
380
|
+
intersection_xs.append(float(x))
|
|
381
|
+
|
|
382
|
+
if intersection_xs:
|
|
383
|
+
new_levels = np.unique(
|
|
384
|
+
np.concatenate([levels, np.asarray(intersection_xs, dtype=float)])
|
|
385
|
+
)
|
|
386
|
+
else:
|
|
387
|
+
new_levels = levels
|
|
388
|
+
|
|
389
|
+
new_corrected_curve = np.interp(new_levels, levels, corrected_curve)
|
|
390
|
+
new_phase_rand_curve = np.interp(new_levels, levels, phase_rand_curve)
|
|
391
|
+
|
|
392
|
+
return new_levels, new_corrected_curve, new_phase_rand_curve
|
|
363
393
|
|
|
364
394
|
def plot_fsc(self, data_curves, other_curves=None, other_curves_lable='Provided FSC'):
|
|
365
395
|
"""
|
|
@@ -413,48 +443,213 @@ class GetStars:
|
|
|
413
443
|
|
|
414
444
|
def plot_feature_zone(self, intersections, levels, corrected_curve, phase_rand_curve):
|
|
415
445
|
"""
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
:param intersections: list of tuples containing intersections in (x,y) coordinates
|
|
419
|
-
:param levels: list of frequency values
|
|
420
|
-
:param corrected_curve: list of corrected FSC value from Relion Star file
|
|
421
|
-
:param phase_rand_curve: list of phase randomized FSC value from Relion
|
|
446
|
+
Plot feature zone and save to image.
|
|
422
447
|
"""
|
|
423
448
|
|
|
449
|
+
levels = np.asarray(levels, dtype=float)
|
|
450
|
+
corrected_curve = np.asarray(corrected_curve, dtype=float)
|
|
451
|
+
phase_rand_curve = np.asarray(phase_rand_curve, dtype=float)
|
|
452
|
+
|
|
453
|
+
valid = (
|
|
454
|
+
np.isfinite(levels)
|
|
455
|
+
& np.isfinite(corrected_curve)
|
|
456
|
+
& np.isfinite(phase_rand_curve)
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
levels = levels[valid]
|
|
460
|
+
corrected_curve = corrected_curve[valid]
|
|
461
|
+
phase_rand_curve = phase_rand_curve[valid]
|
|
462
|
+
|
|
463
|
+
if len(levels) < 2:
|
|
464
|
+
return 0.0, 0.0
|
|
465
|
+
|
|
466
|
+
order = np.argsort(levels)
|
|
467
|
+
levels = levels[order]
|
|
468
|
+
corrected_curve = corrected_curve[order]
|
|
469
|
+
phase_rand_curve = phase_rand_curve[order]
|
|
470
|
+
|
|
471
|
+
valid_intersections = [
|
|
472
|
+
(float(x), float(y))
|
|
473
|
+
for x, y in intersections
|
|
474
|
+
if np.isfinite(x) and np.isfinite(y)
|
|
475
|
+
]
|
|
476
|
+
|
|
477
|
+
valid_intersections = sorted(set(valid_intersections), key=lambda p: p[0])
|
|
478
|
+
|
|
479
|
+
plt.plot(levels, corrected_curve, color='red', label='FSC corrected')
|
|
480
|
+
plt.plot(levels, phase_rand_curve, color='blue', label='Phase randomized')
|
|
481
|
+
|
|
424
482
|
frequency = 1 / self.randomise_from()
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
483
|
+
|
|
484
|
+
# ============================================================
|
|
485
|
+
# FEATURE ZONE (PINK)
|
|
486
|
+
# ============================================================
|
|
487
|
+
# Feature area is independent of the randomization frequency.
|
|
488
|
+
#
|
|
489
|
+
# Count ALL area between the two curves wherever:
|
|
490
|
+
#
|
|
491
|
+
# corrected FSC > phase-randomized FSC
|
|
492
|
+
#
|
|
493
|
+
# over the entire available frequency range.
|
|
494
|
+
|
|
495
|
+
feature_delta = corrected_curve - phase_rand_curve
|
|
496
|
+
|
|
497
|
+
feature_area = np.trapz(
|
|
498
|
+
np.clip(feature_delta, 0, None),
|
|
499
|
+
levels
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
plt.fill_between(
|
|
503
|
+
levels,
|
|
504
|
+
corrected_curve,
|
|
505
|
+
phase_rand_curve,
|
|
506
|
+
where=(corrected_curve >= phase_rand_curve),
|
|
507
|
+
interpolate=True,
|
|
508
|
+
color='pink',
|
|
509
|
+
alpha=0.5,
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
# ============================================================
|
|
513
|
+
# OVERFIT ZONE (BLUE)
|
|
514
|
+
# ============================================================
|
|
515
|
+
# Blue area DOES depend on randomization frequency.
|
|
516
|
+
# It starts exactly at:
|
|
517
|
+
#
|
|
518
|
+
# frequency = 1 / self.randomise_from()
|
|
519
|
+
#
|
|
520
|
+
# and is the positive area between phase-randomized FSC
|
|
521
|
+
# and the x-axis.
|
|
522
|
+
|
|
523
|
+
overfit_area = 0.0
|
|
524
|
+
|
|
525
|
+
if levels[0] <= frequency < levels[-1]:
|
|
526
|
+
# Find the first original data point AFTER the exact
|
|
527
|
+
# randomization frequency.
|
|
528
|
+
start_idx = np.searchsorted(
|
|
529
|
+
levels,
|
|
530
|
+
frequency,
|
|
531
|
+
side='right'
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
# Interpolate the phase-randomized FSC at the exact
|
|
535
|
+
# randomization frequency.
|
|
536
|
+
phase_at_frequency = np.interp(
|
|
537
|
+
frequency,
|
|
538
|
+
levels,
|
|
539
|
+
phase_rand_curve
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# Explicitly insert the exact randomization frequency
|
|
543
|
+
# as the first point.
|
|
544
|
+
overfit_x = np.concatenate(
|
|
545
|
+
([frequency], levels[start_idx:])
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
overfit_phase = np.concatenate(
|
|
549
|
+
([phase_at_frequency], phase_rand_curve[start_idx:])
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
# Count only positive phase-randomized FSC as blue area.
|
|
553
|
+
overfit_area = np.trapz(
|
|
554
|
+
np.clip(overfit_phase, 0, None),
|
|
555
|
+
overfit_x
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
# Draw blue area starting exactly at randomization frequency.
|
|
559
|
+
plt.fill_between(
|
|
560
|
+
overfit_x,
|
|
561
|
+
overfit_phase,
|
|
562
|
+
0,
|
|
563
|
+
where=(overfit_phase >= 0),
|
|
564
|
+
interpolate=True,
|
|
565
|
+
color='blue',
|
|
566
|
+
alpha=0.5,
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
# feature_area = 0.0
|
|
570
|
+
#
|
|
571
|
+
# if valid_intersections:
|
|
572
|
+
# intersection_xs = [x for x, y in valid_intersections]
|
|
573
|
+
#
|
|
574
|
+
# # Use searchsorted instead of exact equality.
|
|
575
|
+
# boundaries = [np.searchsorted(levels, x) for x in intersection_xs]
|
|
576
|
+
# boundaries = [max(0, min(idx, len(levels))) for idx in boundaries]
|
|
577
|
+
# boundaries = sorted(set(boundaries))
|
|
578
|
+
#
|
|
579
|
+
# for i in range(len(boundaries)):
|
|
580
|
+
# idx_start = boundaries[i]
|
|
581
|
+
#
|
|
582
|
+
# if i == len(boundaries) - 1:
|
|
583
|
+
# idx_end = len(levels)
|
|
584
|
+
# else:
|
|
585
|
+
# idx_end = boundaries[i + 1]
|
|
586
|
+
#
|
|
587
|
+
# if idx_end <= idx_start:
|
|
588
|
+
# continue
|
|
589
|
+
#
|
|
590
|
+
# seg_levels = levels[idx_start:idx_end]
|
|
591
|
+
# seg_corrected = corrected_curve[idx_start:idx_end]
|
|
592
|
+
# seg_phase = phase_rand_curve[idx_start:idx_end]
|
|
593
|
+
#
|
|
594
|
+
# if len(seg_levels) < 2:
|
|
595
|
+
# continue
|
|
596
|
+
#
|
|
597
|
+
# finite_segment = (
|
|
598
|
+
# np.all(np.isfinite(seg_levels))
|
|
599
|
+
# and np.all(np.isfinite(seg_corrected))
|
|
600
|
+
# and np.all(np.isfinite(seg_phase))
|
|
601
|
+
# )
|
|
602
|
+
#
|
|
603
|
+
# if not finite_segment:
|
|
604
|
+
# continue
|
|
605
|
+
#
|
|
606
|
+
# above = seg_corrected >= seg_phase
|
|
607
|
+
#
|
|
608
|
+
# plt.fill_between(
|
|
609
|
+
# seg_levels,
|
|
610
|
+
# seg_corrected,
|
|
611
|
+
# seg_phase,
|
|
612
|
+
# where=above,
|
|
613
|
+
# color='pink',
|
|
614
|
+
# alpha=0.5,
|
|
615
|
+
# )
|
|
616
|
+
#
|
|
617
|
+
# if np.all(above):
|
|
618
|
+
# cur_area = np.trapz(
|
|
619
|
+
# seg_corrected - seg_phase,
|
|
620
|
+
# seg_levels,
|
|
621
|
+
# )
|
|
622
|
+
# feature_area += cur_area
|
|
623
|
+
#
|
|
624
|
+
# frequency = 1 / self.randomise_from()
|
|
625
|
+
#
|
|
626
|
+
# closest_idx = int(np.argmin(np.abs(levels - frequency)))
|
|
627
|
+
#
|
|
628
|
+
# overfit_x = levels[closest_idx:]
|
|
629
|
+
# overfit_y = phase_rand_curve[closest_idx:]
|
|
630
|
+
#
|
|
631
|
+
# valid_overfit = np.isfinite(overfit_x) & np.isfinite(overfit_y)
|
|
632
|
+
#
|
|
633
|
+
# overfit_x = overfit_x[valid_overfit]
|
|
634
|
+
# overfit_y = overfit_y[valid_overfit]
|
|
635
|
+
#
|
|
636
|
+
# if len(overfit_x) >= 2:
|
|
637
|
+
# y_values = np.zeros(len(overfit_x))
|
|
638
|
+
# overfit_area = np.trapz(overfit_y, overfit_x)
|
|
639
|
+
#
|
|
640
|
+
# plt.fill_between(
|
|
641
|
+
# overfit_x,
|
|
642
|
+
# overfit_y,
|
|
643
|
+
# y_values,
|
|
644
|
+
# where=(overfit_y >= 0),
|
|
645
|
+
# color='blue',
|
|
646
|
+
# alpha=0.5,
|
|
647
|
+
# )
|
|
648
|
+
# else:
|
|
649
|
+
# overfit_area = 0.0
|
|
650
|
+
|
|
651
|
+
plt.legend(loc='best', fontsize='x-small')
|
|
652
|
+
|
|
458
653
|
zone_image = f'{self.va_dir}/feature_zone.png'
|
|
459
654
|
plt.savefig(zone_image)
|
|
460
655
|
plt.close()
|
|
@@ -564,56 +759,141 @@ class GetStars:
|
|
|
564
759
|
|
|
565
760
|
def feature_zone(self, data_curves):
|
|
566
761
|
"""
|
|
567
|
-
|
|
568
|
-
return quantified area of that zone
|
|
569
|
-
:param data_curves: dictionary contains all curves
|
|
762
|
+
Given two curves, calculate feature zone and overfit zone.
|
|
570
763
|
"""
|
|
571
764
|
|
|
572
765
|
zones = {}
|
|
573
766
|
result = {}
|
|
574
|
-
all_curves = None
|
|
575
|
-
if 'curves' in data_curves.keys():
|
|
576
|
-
all_curves = data_curves['curves']
|
|
577
767
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
768
|
+
all_curves = data_curves.get('curves')
|
|
769
|
+
if not all_curves:
|
|
770
|
+
return result
|
|
771
|
+
|
|
772
|
+
levels = all_curves.get('level')
|
|
773
|
+
corrected_curve = all_curves.get('fsc_corrected')
|
|
774
|
+
|
|
775
|
+
phase_rand_curve = all_curves.get('phaserandomization')
|
|
776
|
+
if phase_rand_curve is None:
|
|
777
|
+
phase_rand_curve = all_curves.get('phaserandmization')
|
|
778
|
+
|
|
779
|
+
masked_curve = all_curves.get('fsc_masked')
|
|
780
|
+
unmasked_curve = all_curves.get('fsc')
|
|
781
|
+
|
|
782
|
+
if levels is None or corrected_curve is None or phase_rand_curve is None:
|
|
783
|
+
return result
|
|
784
|
+
|
|
785
|
+
try:
|
|
786
|
+
levels = np.asarray(levels, dtype=float)
|
|
787
|
+
corrected_curve = np.asarray(corrected_curve, dtype=float)
|
|
788
|
+
phase_rand_curve = np.asarray(phase_rand_curve, dtype=float)
|
|
789
|
+
|
|
790
|
+
min_len = min(len(levels), len(corrected_curve), len(phase_rand_curve))
|
|
791
|
+
|
|
792
|
+
levels = levels[:min_len]
|
|
793
|
+
corrected_curve = corrected_curve[:min_len]
|
|
794
|
+
phase_rand_curve = phase_rand_curve[:min_len]
|
|
795
|
+
|
|
796
|
+
valid = (
|
|
797
|
+
np.isfinite(levels)
|
|
798
|
+
& np.isfinite(corrected_curve)
|
|
799
|
+
& np.isfinite(phase_rand_curve)
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
levels = levels[valid]
|
|
803
|
+
corrected_curve = corrected_curve[valid]
|
|
804
|
+
phase_rand_curve = phase_rand_curve[valid]
|
|
805
|
+
|
|
806
|
+
if len(levels) < 2:
|
|
807
|
+
return result
|
|
808
|
+
|
|
809
|
+
order = np.argsort(levels)
|
|
810
|
+
levels = levels[order]
|
|
811
|
+
corrected_curve = corrected_curve[order]
|
|
812
|
+
phase_rand_curve = phase_rand_curve[order]
|
|
813
|
+
|
|
814
|
+
xs, ys = interpolated_intercepts_general(
|
|
815
|
+
levels,
|
|
816
|
+
corrected_curve,
|
|
817
|
+
phase_rand_curve,
|
|
818
|
+
)
|
|
596
819
|
|
|
597
|
-
if isinstance(levels, np.ndarray) and isinstance(corrected_curve, np.ndarray) and isinstance(phase_rand_curve, np.ndarray):
|
|
598
|
-
xs, ys = interpolated_intercepts_general(levels, corrected_curve, phase_rand_curve)
|
|
599
820
|
intersections = remove_duplicate_intersections(xs, ys)
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
821
|
+
|
|
822
|
+
nlevels, ncorrected_curve, nphase_rand_curve = self.intersections_into_curve(
|
|
823
|
+
intersections,
|
|
824
|
+
levels,
|
|
825
|
+
corrected_curve,
|
|
826
|
+
phase_rand_curve,
|
|
827
|
+
)
|
|
828
|
+
|
|
829
|
+
feature_area, overfit_area = self.plot_feature_zone(
|
|
830
|
+
intersections,
|
|
831
|
+
nlevels,
|
|
832
|
+
ncorrected_curve,
|
|
833
|
+
nphase_rand_curve,
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
if masked_curve is not None and unmasked_curve is not None:
|
|
837
|
+
masked_curve = np.asarray(masked_curve, dtype=float)[:min_len][valid]
|
|
838
|
+
unmasked_curve = np.asarray(unmasked_curve, dtype=float)[:min_len][valid]
|
|
839
|
+
|
|
840
|
+
masked_curve = masked_curve[order]
|
|
841
|
+
unmasked_curve = unmasked_curve[order]
|
|
842
|
+
|
|
843
|
+
masking_area = self.area_difference(
|
|
844
|
+
masked_curve,
|
|
845
|
+
corrected_curve,
|
|
846
|
+
levels,
|
|
847
|
+
)
|
|
848
|
+
|
|
849
|
+
corrected_unmasked_difference = np.nansum(
|
|
850
|
+
corrected_curve - unmasked_curve
|
|
851
|
+
)
|
|
852
|
+
corrected_masked_difference = np.nansum(
|
|
853
|
+
masked_curve - corrected_curve
|
|
854
|
+
)
|
|
855
|
+
|
|
856
|
+
if corrected_unmasked_difference == 0:
|
|
857
|
+
masking_area_ratio = 999
|
|
858
|
+
else:
|
|
859
|
+
masking_area_ratio = abs(
|
|
860
|
+
corrected_masked_difference / corrected_unmasked_difference
|
|
861
|
+
)
|
|
608
862
|
else:
|
|
609
|
-
|
|
863
|
+
masking_area = 0.0
|
|
864
|
+
masking_area_ratio = 0.0
|
|
865
|
+
|
|
866
|
+
feature_area = float(feature_area or 0.0)
|
|
867
|
+
overfit_area = float(overfit_area or 0.0)
|
|
868
|
+
masking_area = float(masking_area or 0.0)
|
|
869
|
+
masking_area_ratio = float(masking_area_ratio or 0.0)
|
|
870
|
+
|
|
610
871
|
zones['feature_zone'] = keep_three_significant_digits(feature_area)
|
|
611
872
|
zones['overfit_zone'] = keep_three_significant_digits(overfit_area)
|
|
612
873
|
zones['masking_area'] = keep_three_significant_digits(masking_area)
|
|
613
874
|
zones['masking_area_ratio'] = keep_three_significant_digits(masking_area_ratio)
|
|
614
|
-
|
|
875
|
+
|
|
876
|
+
total_area = feature_area + overfit_area
|
|
877
|
+
if total_area == 0:
|
|
878
|
+
zones['feature_zone_ratio'] = 0
|
|
879
|
+
else:
|
|
880
|
+
zones['feature_zone_ratio'] = keep_three_significant_digits(
|
|
881
|
+
feature_area / total_area
|
|
882
|
+
)
|
|
883
|
+
|
|
615
884
|
result['feature_zones'] = zones
|
|
616
885
|
|
|
886
|
+
except Exception as exc:
|
|
887
|
+
print(f'Feature zone calculation failed: {exc}')
|
|
888
|
+
result['feature_zones'] = {
|
|
889
|
+
'feature_zone': 0,
|
|
890
|
+
'overfit_zone': 0,
|
|
891
|
+
'masking_area': 0,
|
|
892
|
+
'masking_area_ratio': 0,
|
|
893
|
+
'feature_zone_ratio': 0,
|
|
894
|
+
'error': str(exc),
|
|
895
|
+
}
|
|
896
|
+
|
|
617
897
|
return result
|
|
618
898
|
|
|
619
899
|
|
|
@@ -6888,10 +6888,9 @@ class ValidationAnalysis:
|
|
|
6888
6888
|
start = timeit.default_timer()
|
|
6889
6889
|
errlist = []
|
|
6890
6890
|
result_dict = {}
|
|
6891
|
-
# if strudelapp and self.models:
|
|
6892
6891
|
if self.hmeven and self.hmodd:
|
|
6893
|
-
even = self.hmeven.
|
|
6894
|
-
odd = self.hmodd.
|
|
6892
|
+
even = self.hmeven._iostream.name
|
|
6893
|
+
odd = self.hmodd._iostream.name
|
|
6895
6894
|
full_map = '{}{}'.format(self.workdir, self.mapname)
|
|
6896
6895
|
out_path = '{}_relion'.format(full_map)
|
|
6897
6896
|
print(out_path)
|
|
@@ -6911,16 +6910,26 @@ class ValidationAnalysis:
|
|
|
6911
6910
|
check = locres_filecheck(odd, even, out_path)
|
|
6912
6911
|
if check:
|
|
6913
6912
|
try:
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6913
|
+
map_basename = os.path.splitext(os.path.basename(odd))[0]
|
|
6914
|
+
orgmap = self.rawmap._iostream.name
|
|
6915
|
+
resmap = '{}/{}_relion/{}_{}_locres.mrc'.format(self.workdir, self.mapname, os.path.basename(odd), os.path.basename(even))
|
|
6916
|
+
missing_view_inputs = resmap if not os.path.isfile(resmap) else None
|
|
6917
|
+
|
|
6918
|
+
print(missing_view_inputs)
|
|
6919
|
+
if missing_view_inputs:
|
|
6920
|
+
err = 'Skipping local resolution views; missing input files: {}.'.format(
|
|
6921
|
+
', '.join(missing_view_inputs)
|
|
6922
|
+
)
|
|
6923
|
+
errlist.append(err)
|
|
6924
|
+
sys.stderr.write(err + '\n')
|
|
6925
|
+
else:
|
|
6926
|
+
local_res_chimerax_file = relion_local_res_chimerax(orgmap, resmap, self.workdir)
|
|
6927
|
+
if os.path.isfile(local_res_chimerax_file):
|
|
6928
|
+
vtkpack, chimeraapp = self.surface_envcheck()
|
|
6929
|
+
bindisplay = os.getenv('DISPLAY')
|
|
6930
|
+
run_resmap_chimerax(bindisplay, chimeraapp, local_res_chimerax_file)
|
|
6922
6931
|
except:
|
|
6923
|
-
err = '
|
|
6932
|
+
err = 'Local resolution views error: {}.'.format(sys.exc_info()[1])
|
|
6924
6933
|
errlist.append(err)
|
|
6925
6934
|
sys.stderr.write(err + '\n')
|
|
6926
6935
|
else:
|
|
@@ -6928,6 +6937,8 @@ class ValidationAnalysis:
|
|
|
6928
6937
|
|
|
6929
6938
|
if errlist:
|
|
6930
6939
|
result_dict['err'] = errlist
|
|
6940
|
+
output_json = '{}{}_resmap.json'.format(self.workdir, self.mapname)
|
|
6941
|
+
out_json(result_dict, output_json)
|
|
6931
6942
|
else:
|
|
6932
6943
|
try:
|
|
6933
6944
|
resmap = '{}_ori_resmap.map'.format(odd[:-4])
|
|
@@ -6960,7 +6971,7 @@ class ValidationAnalysis:
|
|
|
6960
6971
|
except (TypeError, ValueError):
|
|
6961
6972
|
res_val = None
|
|
6962
6973
|
if res_val is not None:
|
|
6963
|
-
local_res = localres_histogram(self.hmodd.
|
|
6974
|
+
local_res = localres_histogram(self.hmodd._iostream.name, self.mapname, res_val)
|
|
6964
6975
|
else:
|
|
6965
6976
|
local_res = None
|
|
6966
6977
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|