File: libcheck.py

package info (click to toggle)
coot 1.1.18%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 219,964 kB
  • sloc: cpp: 495,934; python: 35,043; ansic: 26,143; lisp: 22,768; sh: 13,186; makefile: 2,746; awk: 441; xml: 245; csh: 14
file content (259 lines) | stat: -rw-r--r-- 10,656 bytes parent folder | download | duplicates (2)
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# libcheck.py
#
# Copyright 2004, 2005, 2006 by Paul Emsley, The University of York
# Copyright 2005, 2006 by Bernhard Lohkamp
#    Copyright (C) 2007, 2008, 2009 by Bernhard Lohkamp, The University of York
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.


# BL to do:
# coot_utils.debug with given ccp4i_dir and lib file
# else if refmac doesnt exist
#

# this is override-able by the user in their .coot file (for example).
libcheck_exe = "libcheck"

# This files provides an interface to libcheck

# Where @var{code} is @emph{e.g.} "3GP" and @var{ccp4i-project-dir}
# is an optional arg which is the directory to which the libcheck log
# files and pdb file will go.
#
# Return -2 on @var{code} is not a string
# Return -3 on libcheck failure
# Return -4 on refmac failure
# Return @var{imol} on success
# Return @code{handle-read-draw-molecule} error code on failure to
#       read resultant pdb file
#
# Actually, it would be nice to know if this code represented a full
# description - or a minimal one... perhaps we can parse the log
# file and call a pop-up that will tell us.
#
# @var{dict_cif_libin should be a string}.  If it is "" then it is
# ignored.  If it is not "" then it is used to create input to
# libcheck (not a command line argument) so that bespoke dictionary
# libraries can produce coords using "Get Monomer".
#
# might not do all above mentioned things in python, yet
#
def monomer_molecule_from_3_let_code(code, dict_cif_libin,
                                     ccp4i_project_dir = ""):

  import os, stat, shutil

  # return True if log file has "has the minimal description" in it.
  # else return False
  #
  def libcheck_minimal_qm(filename):

    # BL says: a quick fix for now, maybe we want to use something like
    # Paul's call_with_input_file funcn at some point
    ret = False
    try:
        f = open(filename, 'r')
        lines = f.readlines()
        for line in lines:
            if "has the minimal description" in line:
                ret = True
                break
        f.close()
    except:
        print("BL WARNING: couldnt open file ", filename)
    return ret

  # move file_name to some file name with a date extension
  #
  def move_aside(file_name):
    import time
    if (os.path.isfile(file_name)):
        # we use - and not : to avoid hazzle in windows
        extension = time.strftime('%d-%m-%Y-%H-%M-%S')
        new_file_name = file_name + "-" + extension
        try:
          os.rename(file_name, new_file_name)
        except:
          print("BL WARNING:: could not rename file %s to %s" %(file_name, new_file_name))

  # the exe and log_file_name (and command_lines_args perhaps)
  # relative to dir (not the calling dir)
  # BL says:: maybe this should be in coot_utils.py
  def run_command_in_dir(run_dir, exe_name, command_line_args,
                         data_lines, log_file_name, to_screen_flag):
    import os

    print(("BL INFO:: run_command_in_dir dir:"
           "%s exe: %s cl_args: %s data_lines: %s log_file: %s"
           %(run_dir, exe_name, command_line_args, data_lines, log_file_name)))
    current = os.getcwd()
    norm_dir = os.path.normpath(run_dir)
    os.chdir(norm_dir)
    status = coot_utils.popen_command(exe_name, command_line_args, data_lines,
                           log_file_name, to_screen_flag)
    os.chdir(current)
    return status

  def log_file2text(log_file_name, dir):
    f = os.path.join(dir, log_file_name)
    return coot_utils.file2string(f)

  # This gets called in non-graphics mode too.
  #
  def libcheck_monomer_gui(dir_prefix, code_str, cif_file_name,
                           pdb_file_name, post_refmac_pdb_file_name):

    # print "================= coot_utils.debug: libcheck_monomer_gui: dir_prefix: %s   code_str: %s   cif_file_name: %s   pdb_file_name: %s   post_refmac_pdb_file_name: %s" %(dir_prefix, code_str, cif_file_name, pdb_file_name, post_refmac_pdb_file_name)

    if (len(dict_cif_libin) == 0):
      libcheck_input = ["N", "MON " + code_str[0:3], ""]
    else:
      # BL says:: Paul's code says FILE_CIF as argument, but I beleave this should be
      # FILE_L. FILE_CIF is for coordinate cif files and not dictionary cif file (which is
      # what we have here, I think)
      #      libcheck_input = ["N","FILE_CIF " + dict_cif_libin,"MON " + code_str,""]
      libcheck_input = ["N", "FILE_L " + dict_cif_libin,
                        "MON " + code_str, ""]

    log_file_name = "coot-libcheck-"  + code_str + ".log"
    log_file_name_in_dir = os.path.join(dir_prefix, log_file_name)
    refmac_input = ["MODE NEWENTRY", "END"]

    refmac_log_file_name = os.path.join(dir_prefix, "coot-libcheck-refmac-" + code_str + ".log")
    refmac_command_line = ["LIBIN", cif_file_name, "XYZIN", pdb_file_name,
                           "XYZOUT", post_refmac_pdb_file_name]

    move_aside(os.path.join(dir_prefix, "libcheck.lib"))
    #print "passing libcheck these data lines:", libcheck_input

    libcheck_exe_file = coot_utils.find_exe(libcheck_exe, "CBIN", "CCP4_BIN", "PATH")
    if (libcheck_exe_file):
      libstatus = run_command_in_dir(dir_prefix, libcheck_exe_file, [], libcheck_input, log_file_name, True)

      print("BL INFO:: libcheck status:", libstatus)

      if (not coot_utils.isNumber(libstatus)):

        log_text = log_file2text(log_file_name, dir_prefix)
        if (isinstance(log_text, str)):
          coot.simple_text_dialog("Libcheck log", log_text, 200, 400)
          return -1
      else:
        if (libstatus != 0):

          log_text = log_file2text(log_file_name, dir_prefix)
          if isinstance(log_text, str):
            coot.simple_text_dialog("Libcheck log", log_text, 400, 400)
            return -1

        else:
          # we assume libcheck run ok
          #
          # But I now find that libcheck can run OK, but
          # not produce an output file (using dict .cif
          # file from PRODRG).
          #
          # So we first need to check that the output of
          # libcheck exists.
          #
          if (not os.path.isfile(cif_file_name)):
            print("libcheck failed to write the output cif file", cif_file_name)
            log_text = log_file2text(log_file_name, dir_prefix)
            if isinstance(log_text, str):
              coot.simple_text_dialog("Libcheck log", log_text, 400, 400)
            return -1
          else:
            # OK, now let's run refmac:
            #
            libcheck_minimal_desc_status = libcheck_minimal_qm(log_file_name_in_dir)
            refmac_exe = coot_utils.find_exe("refmac5", "CBIN", "CCP4_BIN", "PATH")
            refmac_status = coot_utils.popen_command(refmac_exe, refmac_command_line, refmac_input, refmac_log_file_name)

            print("INFO:: libcheck-minimal? is ", libcheck_minimal_desc_status)

            if (not coot_utils.isNumber(refmac_status)):
              return -4 # refmac fails
            else:
              if (not refmac_status == 0):
                return -4 # refmac fails elsewhere
              else:
                # refmac run ok
                #
                # if there was a minimal description,
                # we get the real cif file in
                # libcheck.lib.
                libcheck_lib = os.path.join(dir_prefix, "libcheck.lib")
                #print "------------- about to copy file %s to %s in dir %s" %(libcheck_lib, cif_file_name, os.getcwd())
                if (os.path.isfile(libcheck_lib)):
                  shutil.copyfile(libcheck_lib, cif_file_name)
                return handle_libcheck_cif_and_pdb(cif_file_name,
                                                   pdb_file_name,
                                                   post_refmac_pdb_file_name)

  def handle_libcheck_cif_and_pdb(cif_file_name, pdb_file_name, post_refmac_pdb_file_name):

    #print "================= coot_utils.debug:: handle-libcheck-cif-and-pdb: cif-file-name: %s pdb-file-name: %s post-refmac-pdb-file-name: %s" %(cif_file_name, pdb_file_name, post_refmac_pdb_file_name)
    if (os.path.isfile(post_refmac_pdb_file_name) and
        os.path.isfile(cif_file_name)):
      pdb_status = coot.handle_read_draw_molecule_with_recentre(
        post_refmac_pdb_file_name, 0)
      if (coot_utils.valid_model_molecule_qm(pdb_status)):
        coot.assign_hetatms(pdb_status)
        move_molecule_here(pdb_status)
        coot.read_cif_dictionary(cif_file_name)
        return pdb_status  # return imol of the ligand
    return -1 # on fail


  # main body
  if not isinstance(code, str):
    print("WARNING:: Oops code %s was not a string " %code)
    return -2
  else:

    # do the files exist already?  If so, just read them in.
    if (ccp4i_project_dir == ""):
      target_dir_name = "coot-ccp4"
      dir_name = coot_utils.get_directory(target_dir_name)
      dir_prefix = os.path.normpath(dir_name)
    else:
      dir_prefix = os.path.normpath(ccp4i_project_dir)
    #print "BL DEBUG:: dir prefix", dir_prefix

    code_str = str(code)

    pdb_file_name = os.path.join(dir_prefix, "libcheck_" + code_str + ".pdb")
    cif_file_name = os.path.join(dir_prefix, "libcheck_" + code_str + ".cif")
    post_refmac_pdb_file_name = os.path.join(dir_prefix, "monomer-" + code_str + ".pdb")

    if (os.path.isfile(post_refmac_pdb_file_name) and
        os.path.isfile(cif_file_name)):
      return handle_libcheck_cif_and_pdb(cif_file_name, pdb_file_name,
                                         post_refmac_pdb_file_name)

    else:
      libcheck_exe_file = coot_utils.find_exe(libcheck_exe, "CBIN", "CCP4_BIN", "PATH")
      if (not libcheck_exe_file):
        coot.info_dialog("You need to setup CCP4 (specifically LIBCHECK) first.")
        return -2
      else:
        v = libcheck_monomer_gui(dir_prefix, code_str, cif_file_name,
                                 pdb_file_name, post_refmac_pdb_file_name)
        # somehow this can be none?! shouldnt
        if (not coot_utils.isNumber(v)):
          v = -1
        return v

#monomer_molecule_from_3_let_code("3GP","")