-
Notifications
You must be signed in to change notification settings - Fork 8
/
single_soakdb.py
242 lines (203 loc) · 8.78 KB
/
single_soakdb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
import glob
from setup_django import setup_django
setup_django()
from functions import db_functions
from functions import misc_functions
from functions.pandda_functions import *
from xchem_db.models import *
from utils.refinement import RefinementObjectFiles
from dateutil.parser import parse
import argparse
from django.db import transaction
# functions called in steps
def is_date(string):
try:
parse(string)
return True
except ValueError:
return False
@transaction.atomic
def transfer_file(data_file):
maint_exists = db_functions.check_table_sqlite(data_file, 'mainTable')
if maint_exists == 1:
print('transferring crystal data...')
db_functions.transfer_table(translate_dict=db_functions.crystal_translations(), filename=data_file,
model=Crystal)
print('transferring lab data...')
db_functions.transfer_table(translate_dict=db_functions.lab_translations(), filename=data_file,
model=Lab)
print('transferring refinement data...')
db_functions.transfer_table(translate_dict=db_functions.refinement_translations(), filename=data_file,
model=Refinement)
print('transferring dimple data...')
db_functions.transfer_table(translate_dict=db_functions.dimple_translations(), filename=data_file,
model=Dimple)
print('transferring data processing data...')
db_functions.transfer_table(translate_dict=db_functions.data_processing_translations(),
filename=data_file, model=DataProcessing)
soakdb_query = SoakdbFiles.objects.get(filename=data_file)
soakdb_query.status = 2
soakdb_query.save()
# end of functions called in steps
@transaction.atomic
# step 1 - check the file to get it's status
def check_file(filename):
status=2
# remove any newline characters
filename_clean = filename.rstrip('\n')
# find the relevant entry in the soakdbfiles table
soakdb_query = list(SoakdbFiles.objects.filter(filename=filename_clean))
# raise an exception if the file is not in the soakdb table - not necessary here, I think
# if len(soakdb_query) == 0:
# print('LEN=0')
# out, err, prop = db_functions.pop_soakdb(filename_clean)
# db_functions.pop_proposals(prop)
# only one entry should exist per file
if len(soakdb_query) == 1:
# get the filename back from the query
data_file = soakdb_query[0].filename
# add the file to the list of those that have been checked
# checked.append(data_file)
# get the modification date as stored in the db
old_mod_date = soakdb_query[0].modification_date
# get the current modification date of the file
current_mod_date = misc_functions.get_mod_date(data_file)
# get the id of the entry to write to
id_number = soakdb_query[0].id
if not old_mod_date:
soakdb_query[0].modification_date = current_mod_date
soakdb_query[0].save()
old_mod_date = 0
# if the file has changed since the db was last updated for the entry, change status to indicate this
try:
if int(current_mod_date) > int(old_mod_date):
update_status = SoakdbFiles.objects.get(id=id_number)
update_status.status = 1
status = 1
update_status.save()
except ValueError:
raise Exception(str('current_mod_date: ' + str(current_mod_date)
+ ', old_mod_date: ' + str(old_mod_date)))
print(current_mod_date)
print(old_mod_date)
# if there is more than one entry, raise an exception (should never happen - filename field is unique)
if len(soakdb_query) > 1:
raise Exception('More than one entry for file! Something has gone wrong!')
# if the file is not in the database at all
if len(soakdb_query) == 0:
print('This is a new soakDB file, just setting it up in the database!')
# add the file to soakdb
out, err, proposal = db_functions.pop_soakdb(filename_clean)
# add the proposal to proposal
db_functions.pop_proposals(proposal)
# retrieve the new db entry
soakdb_query = list(SoakdbFiles.objects.filter(filename=filename_clean))
# get the id to update
id_number = soakdb_query[0].id
# update the relevant status to 0, indicating it as a new file
update_status = SoakdbFiles.objects.get(id=id_number)
update_status.status = 0
update_status.save()
status = 0
# else:
# print('The file has not been updated, using existing XCDB data...')
# status = 2
# if the lab table is empty, no data has been transferred from the datafiles, so set status of everything to 0
lab = list(Lab.objects.all())
if not lab:
# this is to set all file statuses to 0 (new file)
soakdb = SoakdbFiles.objects.all()
for filename in soakdb:
filename.status = 0
filename.save()
return status
@transaction.atomic
# Step 2 - identify whether the file is new or changed (from filename status in soakdb) and upload to db
def run_transfer(filename):
status_query = SoakdbFiles.objects.get(filename=filename).status
print('status query: ' + str(status_query) + '(0=new, 1=updated)')
# if it is a changed file - do the delete things
if status_query == 1:
# maint_exists = db_functions.check_table_sqlite(filename, 'mainTable')
#
# if maint_exists == 1:
soakdb_query = SoakdbFiles.objects.get(filename=filename)
print('Updating/adding a new entry for file... (not deleting)')
#soakdb_query.delete()
# the next step is always the same
out, err, proposal = db_functions.pop_soakdb(filename)
db_functions.pop_proposals(proposal)
transfer_file(filename)
@transaction.atomic
# step 3 - create symlinks to bound-state pdbs
def create_links(filename, link_dir):
to_search = Crystal.objects.filter(visit__filename=filename)
crystals = Refinement.objects.filter(crystal_name__in=to_search, outcome__gte=4).filter(outcome__lte=6)
for crystal in crystals:
pth = os.path.join(link_dir,
crystal.crystal_name.target.target_name,
str(crystal.crystal_name.crystal_name + '.pdb'))
smiles = crystal.crystal_name.compound.smiles
prod_smiles = crystal.crystal_name.product
try:
if not os.path.exists(os.readlink(pth)):
os.unlink(pth)
except FileNotFoundError:
pass
if not os.path.isdir('/'.join(pth.split('/')[:-1])):
os.makedirs('/'.join(pth.split('/')[:-1]))
file_obj = RefinementObjectFiles(refinement_object=crystal)
file_obj.find_bound_file()
if file_obj.bound_conf:
try:
if not os.path.isfile(file_obj.bound_conf):
print('path: ' + file_obj.bound_conf + ' does not exist!')
os.symlink(file_obj.bound_conf, pth)
if prod_smiles:
smi = prod_smiles
elif smiles:
smi = smiles
# if smiles:
smi_pth = pth.replace('.pdb', '_smiles.txt')
with open(smi_pth, 'w') as f:
f.write(str(smi))
f.close()
except:
raise Exception(file_obj.bound_conf)
else:
crystal.outcome = 3
crystal.save()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"-s",
"--soakdb_file",
default='',
help="SoakDB file to be put into the database",
required=True,
)
parser.add_argument(
"-o",
"--output_directory",
default='',
help="Output directory where bound-state pdb files will be",
required=True,
)
args = vars(parser.parse_args())
filename = args["soakdb_file"]
link_dir = args["output_directory"]
print('Will process: ' + filename)
print('symlinks to the bound-state pdbs will be found in: ' + link_dir)
print('Checking wether ' + filename + ' is a new or existing entry in XCDB...')
status = check_file(filename)
print(status)
if status==0 or status==1:
print('Transferring the data from the soakDB file into XCDB (this may take a while!)...')
run_transfer(filename)
print('Creating the symbolic links to the bound-state pdb files...')
create_links(filename, link_dir)
print('Telling the database this file is now up-to-date...')
sdb = SoakdbFiles.objects.get(filename=filename)
sdb.status = 2
sdb.save()
print('Done :)')