Пример #1
0
 def _parse_special_cases(self, cmd, args, arguments, i, li):
     if cmd in ('TITL', 'REM'):
         args = args.strip()
         if args: arg_tuple = (args, )
         else: arg_tuple = ()
         return (cmd, arg_tuple)
     if cmd == 'SYMM':
         if args is None:
             raise shelx_error("illegal argument '%s'", i, args)
         return (cmd, (self.symm_space.sub('', args).upper(), ))
     if cmd == 'EQIV':
         m = self._eqiv_pat.search(args)
         if m is None:
             raise shelx_error("illegal argument '%s'", i, args)
         try:
             idx = int(m.group(1))
         except ValueError:
             raise shelx_error("illegal argument '%s'", i, m.group(1))
         return (cmd, (idx, self.symm_space.sub('', m.group(2)).upper()))
     if cmd == 'SFAC':
         sfac_args = []
         for e in arguments:
             try:
                 sfac_args.append(float(e))
             except ValueError:
                 sfac_args.append(e)
         return (cmd, tuple(sfac_args))
     return None
Пример #2
0
 def _parse_special_cases(self, cmd, args, arguments, i, li):
     if cmd in ("TITL", "REM"):
         args = args.strip()
         if args:
             arg_tuple = (args,)
         else:
             arg_tuple = ()
         return (cmd, arg_tuple)
     if cmd == "SYMM":
         if args is None:
             raise shelx_error("illegal argument '%s'", i, args)
         return (cmd, (self.symm_space.sub("", args).upper(),))
     if cmd == "EQIV":
         m = self._eqiv_pat.search(args)
         if m is None:
             raise shelx_error("illegal argument '%s'", i, args)
         try:
             idx = int(m.group(1))
         except ValueError:
             raise shelx_error("illegal argument '%s'", i, m.group(1))
         return (cmd, (idx, self.symm_space.sub("", m.group(2)).upper()))
     if cmd == "SFAC":
         sfac_args = []
         for e in arguments:
             try:
                 sfac_args.append(float(e))
             except ValueError:
                 sfac_args.append(e)
         return (cmd, tuple(sfac_args))
     return None
Пример #3
0
 def filtered_commands(self):
   active_afix = False
   for command, line in self.command_stream:
     cmd, args = command[0], command[-1]
     if cmd in ('AFIX', 'HKLF'):
       if cmd == 'AFIX' and not args:
         raise shelx_error("too few arguments", line)
       if active_afix:
         if n_afixed != n_expected_afixed:
           raise shelx_error("wrong number of afixed atoms", line)
         self.builder.end_geometrical_constraint()
         active_afix = False
         n_afixed = 0
       if cmd == 'HKLF':
         yield command, line
         continue
       mn = args[0]
       if mn == 0: continue
       m,n = divmod(mn, 10)
       d, sof, u = (None,)*3
       params = args[1:]
       if not params: pass
       elif len(params) == 1: d = params[0]
       elif len(params) == 3: d, sof = params[0:]
       elif len(params) == 4: d, sof, u = params[0:]
       else: raise shelx_error("too many arguments", line)
       info = self.constraints.get(m)
       if info is not None:
         constraint_name, pivot_relative_pos = info
         constraint_type = self.builder.make_geometrical_constraint_type(
           constraint_name)
         self.builder.start_geometrical_constraint(
           type_=constraint_type,
           bond_length=d,
           rotating=n in (7, 8),
           stretching=n in (4, 8),
           pivot_relative_pos=pivot_relative_pos)
         n_expected_afixed = constraint_type.n_constrained_sites
         active_afix = True
         n_afixed = 0
     elif cmd == '__ATOM__':
       if active_afix:
         if sof is not None: args[4] = sof
         if u is not None and len(args) == 6: args[-1] = u
         n_afixed += 1
       yield command, line
     else:
       yield command, line
Пример #4
0
 def filtered_commands(self):
   active_afix = False
   for command, line in self.command_stream:
     cmd, args = command[0], command[-1]
     if cmd in ('AFIX', 'HKLF'):
       if cmd == 'AFIX' and not args:
         raise shelx_error("too few arguments", line)
       if active_afix:
         if n_afixed != n_expected_afixed:
           raise shelx_error("wrong number of afixed atoms", line)
         self.builder.end_geometrical_constraint()
         active_afix = False
         n_afixed = 0
       if cmd == 'HKLF':
         yield command, line
         continue
       mn = args[0]
       if mn == 0: continue
       m,n = divmod(mn, 10)
       d, sof, u = (None,)*3
       params = args[1:]
       if not params: pass
       elif len(params) == 1: d = params[0]
       elif len(params) == 3: d, sof = params[0:]
       elif len(params) == 4: d, sof, u = params[0:]
       else: raise shelx_error("too many arguments", line)
       info = self.constraints.get(m)
       if info is not None:
         constraint_name, pivot_relative_pos = info
         constraint_type = self.builder.make_geometrical_constraint_type(
           constraint_name)
         self.builder.start_geometrical_constraint(
           type_=constraint_type,
           bond_length=d,
           rotating=n in (7, 8),
           stretching=n in (4, 8),
           pivot_relative_pos=pivot_relative_pos)
         n_expected_afixed = constraint_type.n_constrained_sites
         active_afix = True
         n_afixed = 0
     elif cmd == '__ATOM__':
       if active_afix:
         if sof is not None: args[4] = sof
         if u is not None and len(args) == 6: args[-1] = u
         n_afixed += 1
       yield command, line
     else:
       yield command, line
Пример #5
0
 def lex_scatterer(self, args, scatterer_index):
     name = args[0]
     n = int(args[1])
     n_vars = len(args) - 2
     if n_vars == 5 or (not self.strictly_shelxl and n_vars == 6):
         values, behaviours = self.decode_variables(args[2:7],
                                                    u_iso_idx=n_vars - 1)
         u = values[4]
         isotropic = True
     elif n_vars == 10:
         unit_cell = self.builder.crystal_symmetry.unit_cell()
         values, behaviours = self.decode_variables(
             args[2:-3] + (args[-1], args[-2], args[-3]), u_iso_idx=None)
         u = adptbx.u_cif_as_u_star(unit_cell, values[-6:])
         isotropic = False
     else:
         raise shelx_error("wrong number of parameters for scatterer",
                           self.line)
     site = values[0:3]
     occ = values[3]
     scattering_type = eltbx.xray_scattering.get_standard_label(
         self.label_for_sfac[n],  # works thank to (a) above
         exact=True)
     scatterer = xray.scatterer(label=name,
                                site=site,
                                occupancy=occ,
                                u=u,
                                scattering_type=scattering_type)
     if (not isotropic or not isinstance(behaviours[-1], tuple)
             or behaviours[-1][0] != constant_times_u_eq):
         self.scatterer_to_bind_u_eq_to = (scatterer, scatterer_index)
     return scatterer, behaviours
Пример #6
0
    def _parse_general_case(self, cmd, cmd_residue, arguments, i, li):
        toks = []
        for j, arg in enumerate(arguments):
            try:
                toks.append(float(arg))
            except ValueError:
                if cmd == 'RESI':
                    toks.append(arg)
                else:
                    m = self._atom_name_pat.match(arg)
                    if m is None:
                        raise shelx_error("illegal argument '%s'", i, arg)
                    name, symmetry, resnum, plus_minus = m.group(
                        'name', 'symmetry', 'resnum', 'plusminus')
                    if name is not None:
                        if resnum is not None: resnum = int(resnum)
                        if symmetry is not None: symmetry = int(symmetry)
                        toks.append(
                            tokens.atomname_token(name=name,
                                                  symmetry=symmetry,
                                                  residue_number=resnum,
                                                  plus_minus=plus_minus))
                        continue
                    element, resnum = m.group('element', 'resnum')
                    if element is not None:
                        toks.append(
                            tokens.element_token(element=element,
                                                 residue_number=resnum))
                        continue

                    if m.group('range') == '>':
                        toks.append((tokens.forward_range_tok, ))
                    elif m.group('range') == '<':
                        toks.append((tokens.backward_range_tok, ))
        if cmd_residue:
            return (cmd, cmd_residue, tuple(toks))
        else:
            if cmd not in self.shelx_commands:
                if cmd[0] == 'Q':
                    toks = (int(cmd[1:]), ) + tuple(toks)
                    cmd = '__Q_PEAK__'
                else:
                    toks = (cmd, ) + tuple(toks)
                    cmd = '__ATOM__'
            else:
                toks = tuple(toks)
            return (cmd, toks)
Пример #7
0
    def _parse_general_case(self, cmd, cmd_residue, arguments, i, li):
        toks = []
        for j, arg in enumerate(arguments):
            try:
                toks.append(float(arg))
            except ValueError:
                if cmd == "RESI":
                    toks.append(arg)
                else:
                    m = self._atom_name_pat.match(arg)
                    if m is None:
                        raise shelx_error("illegal argument '%s'", i, arg)
                    name, symmetry, resnum, plus_minus = m.group("name", "symmetry", "resnum", "plusminus")
                    if name is not None:
                        if resnum is not None:
                            resnum = int(resnum)
                        if symmetry is not None:
                            symmetry = int(symmetry)
                        toks.append(
                            tokens.atomname_token(
                                name=name, symmetry=symmetry, residue_number=resnum, plus_minus=plus_minus
                            )
                        )
                        continue
                    element, resnum = m.group("element", "resnum")
                    if element is not None:
                        toks.append(tokens.element_token(element=element, residue_number=resnum))
                        continue

                    if m.group("range") == ">":
                        toks.append((tokens.forward_range_tok,))
                    elif m.group("range") == "<":
                        toks.append((tokens.backward_range_tok,))
        if cmd_residue:
            return (cmd, cmd_residue, tuple(toks))
        else:
            if cmd not in self.shelx_commands:
                if cmd[0] == "Q":
                    toks = (int(cmd[1:]),) + tuple(toks)
                    cmd = "__Q_PEAK__"
                else:
                    toks = (cmd,) + tuple(toks)
                    cmd = "__ATOM__"
            else:
                toks = tuple(toks)
            return (cmd, toks)
Пример #8
0
 def process_possible_constrained_occupancy(self,
                                            scatterer_index,
                                            scatterer,
                                            occupancy_behaviour):
   if self.builder_does_occupancy_pair_affine_constraint:
     try:
       kind, coeff, free_var_idx = occupancy_behaviour
     except (TypeError, ValueError):
       pass
     else:
       if not self.free_variable:
         raise shelx_error("An instruction FVAR needs to appear before "
                           "this point in the file,", self.line)
       coeff /= scatterer.weight_without_occupancy()
       r_coeff = scitbx.math.continued_fraction.from_real(
         coeff, eps=1e-5).as_rational()
       coeff = round(r_coeff.numerator()/r_coeff.denominator(), ndigits=5)
       if kind == constant_times_independent_scalar_parameter:
         self.occupancies_depending_on_free_variable.setdefault(
           free_var_idx, []).append((coeff, 0, scatterer_index))
       elif kind == constant_times_independent_scalar_parameter_minus_1:
         self.occupancies_depending_on_free_variable.setdefault(
           free_var_idx, []).append((coeff, -1, scatterer_index))
Пример #9
0
 def process_possible_constrained_occupancy(self,
                                            scatterer_index,
                                            scatterer,
                                            occupancy_behaviour):
   if self.builder_does_occupancy_pair_affine_constraint:
     try:
       kind, coeff, free_var_idx = occupancy_behaviour
     except (TypeError, ValueError):
       pass
     else:
       if not self.free_variable:
         raise shelx_error("An instruction FVAR needs to appear before "
                           "this point in the file,", self.line)
       coeff /= scatterer.weight_without_occupancy()
       r_coeff = scitbx.math.continued_fraction.from_real(
         coeff, eps=1e-5).as_rational()
       coeff = round(r_coeff.numerator()/r_coeff.denominator(), ndigits=5)
       if kind == constant_times_independent_scalar_parameter:
         self.occupancies_depending_on_free_variable.setdefault(
           free_var_idx, []).append((coeff, 0, scatterer_index))
       elif kind == constant_times_independent_scalar_parameter_minus_1:
         self.occupancies_depending_on_free_variable.setdefault(
           free_var_idx, []).append((coeff, -1, scatterer_index))
Пример #10
0
 def lex_scatterer(self, args, scatterer_index):
   name = args[0]
   n = int(args[1])
   n_vars = len(args) - 2
   if n_vars == 5 or (not self.strictly_shelxl and n_vars == 6):
     values, behaviours = self.decode_variables(
       args[2:7],
       u_iso_idx=n_vars-1)
     u = values[4]
     isotropic = True
   elif n_vars == 10:
     unit_cell = self.builder.crystal_symmetry.unit_cell()
     values, behaviours = self.decode_variables(
       args[2:-3] + (args[-1], args[-2], args[-3]),
       u_iso_idx=None)
     u = adptbx.u_cif_as_u_star(unit_cell, values[-6:])
     isotropic = False
   else:
     raise shelx_error("wrong number of parameters for scatterer",
                       self.line)
   site = values[0:3]
   occ = values[3]
   scattering_type = eltbx.xray_scattering.get_standard_label(
     self.label_for_sfac[n], # works thank to (a) above
     exact=True)
   scatterer = xray.scatterer(
     label           = name,
     site            = site,
     occupancy       = occ,
     u               = u,
     scattering_type = scattering_type)
   if (not isotropic
       or not isinstance(behaviours[-1], tuple)
       or behaviours[-1][0] != constant_times_u_eq):
     self.scatterer_to_bind_u_eq_to = (scatterer, scatterer_index)
   return scatterer, behaviours
Пример #11
0
 def filtered_commands(self):
   from scitbx.math import continued_fraction
   temperature = 20
   for command, line in self.command_stream:
     cmd, args = command[0], command[-1]
     n_args = len(args)
     if cmd == 'OMIT':
       if n_args == 3 and isinstance(args[0], float):
         self.instructions.setdefault('omit_hkl', [])
         self.instructions['omit_hkl'].append([int(i) for i in args])
       elif n_args == 2 and isinstance(args[0], float):
         self.instructions['omit'] = {
           's': args[0],
           'two_theta': args[1]}
       else:
         yield command, line
     elif cmd == 'SHEL':
       if args:
         shel = {'lowres': args[0]}
         if n_args > 1:
           shel['highres'] = args[1]
     elif cmd == 'MERG':
       if args:
         self.instructions['merg'] = args[0]
     elif cmd == 'TEMP':
       if len(args) > 1:
         raise shelx_error("TEMP takes at most 1 argument")
       if args: temperature = args[0]
       self.instructions['temp'] = temperature
       self.builder.temperature_in_celsius = temperature
     elif cmd == 'WGHT':
       if n_args > 6:
         raise shelx_error("Too many argument for %s" % cmd, line)
       default_weighting_scheme = { 'a': 0.1,
                                    'b': 0,
                                    'c': 0,
                                    'd': 0,
                                    'e': 0,
                                    'f': 1/3 }
       weighting_scheme = dict([
         (key, (arg is not None and arg) or default_weighting_scheme[key])
         for key, arg in itertools.izip_longest('abcdef', args) ])
       self.instructions['wght'] = weighting_scheme
       self.builder.make_shelx_weighting_scheme(**weighting_scheme)
     elif cmd == 'HKLF':
       # only ONE HKLF instruction allowed
       assert 'hklf' not in self.instructions
       hklf = {'s': 1, 'matrix': sgtbx.rot_mx()}
       hklf['n'] = args[0]
       if n_args > 1:
         hklf['s'] = args[1]
         if n_args > 2:
           assert n_args > 10
           mx = [ continued_fraction.from_real(e, eps=1e-3).as_rational()
                  for e in args[2:11] ]
           den = reduce(rational.lcm, [ r.denominator() for r in mx ])
           nums = [ r.numerator()*(den//r.denominator()) for r in mx ]
           hklf['matrix'] = sgtbx.rot_mx(nums, den)
           if n_args > 11:
             hklf['wt'] = args[11]
             if n_args == 13:
               hklf['m'] = args[12]
       self.instructions['hklf'] = hklf
       assert not self.builder or ('wt' not in hklf and 'm' not in hklf)
       self.builder.create_shelx_reflection_data_source(
         format=hklf['n'],
         indices_transform=hklf['matrix'],
         data_scale=hklf['s'])
       if 'basf' in self.instructions and hklf['n'] == 5:
         self.builder.make_non_merohedral_twinning_with_transformed_hkl(
           fractions=self.instructions['basf'])
     elif cmd == 'TWIN':
       # only ONE twin instruction allowed
       assert 'twin' not in self.instructions
       twin = {}
       if n_args > 0:
         assert n_args >= 9
         twin['matrix'] = sgtbx.rt_mx(
           sgtbx.rot_mx([int(i) for i in args[0:9]]))
         if n_args > 9:
           twin['n'] = args[9]
       self.instructions['twin'] = twin
       if 'basf' in self.instructions: self.issue_merohedral_twinning()
     elif cmd == 'BASF':
       self.instructions['basf'] = args
       if 'twin' in self.instructions: self.issue_merohedral_twinning()
     elif cmd == 'EXTI':
       if len(args) == 1:
         self.instructions['exti'] = args[0]
     else:
       yield command, line
   else:
     # All token have been read without errors or early bailout
     assert 'hklf' in self.instructions, "Missing HKLF instruction"
Пример #12
0
 def filtered_commands(self):
   self.label_for_sfac = None
   overall_scale = None
   scatterer_index = 0
   conformer_index = 0
   sym_excl_index = 0
   part_sof = None
   current_residue = (None, None)
   line_of_scatterer_named = {}
   in_the_midst_of_atom_list = False
   idx_assigned_by_builder_to_free_var_idx = {}
   builder = self.builder
   if self.builder_does_occupancy_pair_affine_constraint:
     self.occupancies_depending_on_free_variable = {}
   for command, line in self.command_stream:
     self.line = line
     cmd, args = command[0], command[-1]
     if cmd == 'SFAC':
       builder.make_structure()
       if len(args) == 15 and isinstance(args[1], float):
         raise NotImplementedError(
           '''SFAC label a1 b1 a2 b2 a3 b3 a4 b4 c f' f" mu r wt''')
       self.label_for_sfac = ('*',) + args # (a) working around
                                           #     ShelXL 1-based indexing
     elif cmd == 'FVAR':
       if overall_scale is None:
         overall_scale = args[0]
         self.free_variable = args # (b) ShelXL indexes into the whole array
       else:
         # ShelXL allows for more than one FVAR instruction
         self.free_variable = self.free_variable + args
     elif cmd == 'PART':
       part_sof = None
       conformer_index = 0
       sym_excl_index = 0
       part_number = 0
       if args:
         part_number = int(args[0])
       if len(args) == 2:
         part_sof = self.decode_one_variable(args[1])
       if part_number > 0: conformer_index = part_number
       elif part_number < 0: sym_excl_index = abs(part_number)
     elif cmd == "RESI":
       current_residue = args
       self.builder.add_residue(*current_residue)
     elif cmd == '__ATOM__':
       if not in_the_midst_of_atom_list:
         if self.label_for_sfac is None:
           raise shelx_error("An instruction SFAC needs to appear before "
                             "this point in the file,", self.line)
         in_the_midst_of_atom_list = True
       scatterer, behaviour_of_variable = self.lex_scatterer(
         args, scatterer_index)
       residue_number, residue_class = current_residue
       name = scatterer.label.upper()
       line_1 = line_of_scatterer_named.get((residue_number, name))
       if line_1 is not None:
         raise shelx_error("Residue #%i has two scatterers named %s, "
                           "(with perhaps a difference in letter case)"
                           "defined at lines %i and %i"
                           % (residue_number, name, line, line_1),
                           line=None)
       line_of_scatterer_named[(residue_number, name)] = line
       if (conformer_index or sym_excl_index) and part_sof:
         scatterer.occupancy, behaviour_of_variable[3] = part_sof
       builder.add_scatterer(scatterer, behaviour_of_variable,
                             occupancy_includes_symmetry_factor=True,
                             conformer_index=conformer_index,
                             sym_excl_index=sym_excl_index,
                             residue_number=residue_number,
                             residue_class=residue_class)
       # As the builder accepted the scatterer, we assume that it called
       # scatterer.apply_symmetry so that scatterer.multiplicity and dependents
       # are correctly set. Hence our fetching the scatterer from the builder
       # instead of using the pre-existing local variable.
       scatterer = builder.structure.scatterers()[-1]
       self.process_possible_constrained_occupancy(scatterer_index,
                                                   scatterer,
                                                   behaviour_of_variable[3])
       self.process_possible_u_iso_constraints(scatterer_index,
                                               behaviour_of_variable[4])
       scatterer_index += 1
     elif cmd == '__Q_PEAK__':
       assert not self.strictly_shelxl,\
              "Q-peaks amidst atoms in strict ShelXL model"
       builder.add_electron_density_peak(site = args[2:5],
                                              height = args[-1])
     else:
       yield command, line
   self.process_occupancies_depending_on_free_variable()
Пример #13
0
 def raise_parameter_error():
   raise shelx_error(
     "scatterer parameter #%d '%s'", line, i_cv+1, coded_variable)
Пример #14
0
 def __iter__(self):
     """
 Yields the commands in self.file as tuples:
   - either (cmd, args) where args is a tuple,
     e.g. ('CELL', (0.71073, 1, 2, 3, 90, 90, 90))
   - or (cmd, (residue_class, residue_number), args) for those commands
     which can be suffixed by a residue, e.g.
     ('HFIX', (parser.residue_number_tok, 1), (23, ))
 Notes:
   - For atoms, cmd is '__ATOM__' and the name is the first argument
   - For so-called Q-peaks, cmd is '__Q_PEAK__' and the number is the
     first argument
   - In args, floating point items are reported as is whereas any
     string comes as (type, value) where type is one of the class
     constants defined just above this method (actually, for
     the residue_number_tok, the value is an integer stored as a float).
   - The atomic refinable variables are not decoded: this is the job of
     a parser, not of a lexer.
 """
     continued = False
     for i, li in enumerate(self.file):
         if not li: continue
         if continued:
             m = self._continuation_pat.search(li)
             if m is None:
                 raise shelx_error("illegal continuation line error", i)
             cont_args, continued = m.groups()
             arguments.extend(cont_args.split())
         else:
             m = self._cmd_pat.search(li)
             if m is None:
                 if li[0].isspace(): continue
                 else:
                     m = self._include_filename_pat.search(li)
                     if m is not None:
                         cmd, filename = m.group(1, 2)
                         yield (cmd, filename), i
                         continue
                 raise shelx_error("illegal command or atom name error", i)
             cmd = m.group(1) or m.group(6)
             if cmd:
                 cmd = cmd.upper()
                 cmd_residue = None
             else:
                 (cmd, cmd_residue_class,
                  cmd_residue_number) = m.group(3, 4, 5)
                 cmd = cmd.upper()
                 if cmd_residue_class:
                     cmd_residue = (tokens.residue_class_tok,
                                    cmd_residue_class.upper())
                 elif cmd_residue_number:
                     cmd_residue = (tokens.residue_number_tok,
                                    int(cmd_residue_number))
                 else:
                     cmd_residue = (tokens.all_residues_tok, )
             args = m.group(2) or m.group(7) or ""
             continued = m.group(8)
             arguments = args.split()
         if not continued:
             result = self._parse_special_cases(cmd, args, arguments, i, li)
             if result is None:
                 result = self._parse_general_case(cmd, cmd_residue,
                                                   arguments, i, li)
             yield result, i
             if cmd == 'HKLF': break
Пример #15
0
 def filtered_commands(self):
   from scitbx.math import continued_fraction
   temperature = 20
   for command, line in self.command_stream:
     cmd, args = command[0], command[-1]
     n_args = len(args)
     if cmd == 'OMIT':
       if n_args == 3 and isinstance(args[0], float):
         self.instructions.setdefault('omit_hkl', [])
         self.instructions['omit_hkl'].append([int(i) for i in args])
       elif n_args == 2 and isinstance(args[0], float):
         self.instructions['omit'] = {
           's': args[0],
           'two_theta': args[1]}
       else:
         yield command, line
     elif cmd == 'SHEL':
       if args:
         shel = {'lowres': args[0]}
         if n_args > 1:
           shel['highres'] = args[1]
     elif cmd == 'MERG':
       if args:
         self.instructions['merg'] = args[0]
     elif cmd == 'TEMP':
       if len(args) > 1:
         raise shelx_error("TEMP takes at most 1 argument")
       if args: temperature = args[0]
       self.instructions['temp'] = temperature
       self.builder.temperature_in_celsius = temperature
     elif cmd == 'WGHT':
       if n_args > 6:
         raise shelx_error("Too many argument for %s" % cmd, line)
       default_weighting_scheme = { 'a': 0.1,
                                    'b': 0,
                                    'c': 0,
                                    'd': 0,
                                    'e': 0,
                                    'f': 1/3 }
       weighting_scheme = dict([
         (key, (arg is not None and arg) or default_weighting_scheme[key])
         for key, arg in itertools.izip_longest('abcdef', args) ])
       self.instructions['wght'] = weighting_scheme
       self.builder.make_shelx_weighting_scheme(**weighting_scheme)
     elif cmd == 'HKLF':
       # only ONE HKLF instruction allowed
       assert 'hklf' not in self.instructions
       hklf = {'s': 1, 'matrix': sgtbx.rot_mx()}
       hklf['n'] = args[0]
       if n_args > 1:
         hklf['s'] = args[1]
         if n_args > 2:
           assert n_args > 10
           mx = [ continued_fraction.from_real(e, eps=1e-3).as_rational()
                  for e in args[2:11] ]
           den = reduce(rational.lcm, [ r.denominator() for r in mx ])
           nums = [ r.numerator()*(den//r.denominator()) for r in mx ]
           hklf['matrix'] = sgtbx.rot_mx(nums, den)
           if n_args > 11:
             hklf['wt'] = args[11]
             if n_args == 13:
               hklf['m'] = args[12]
       self.instructions['hklf'] = hklf
       assert not self.builder or ('wt' not in hklf and 'm' not in hklf)
       self.builder.create_shelx_reflection_data_source(
         format=hklf['n'],
         indices_transform=hklf['matrix'],
         data_scale=hklf['s'])
       if 'basf' in self.instructions and hklf['n'] == 5:
         self.builder.make_non_merohedral_twinning_with_transformed_hkl(
           fractions=self.instructions['basf'])
     elif cmd == 'TWIN':
       # only ONE twin instruction allowed
       assert 'twin' not in self.instructions
       twin = {}
       if n_args > 0:
         assert n_args >= 9
         twin['matrix'] = sgtbx.rt_mx(
           sgtbx.rot_mx([int(i) for i in args[0:9]]))
         if n_args > 9:
           twin['n'] = args[9]
       self.instructions['twin'] = twin
       if 'basf' in self.instructions: self.issue_merohedral_twinning()
     elif cmd == 'BASF':
       self.instructions['basf'] = args
       if 'twin' in self.instructions: self.issue_merohedral_twinning()
     elif cmd == 'EXTI':
       if len(args) == 1:
         self.instructions['exti'] = args[0]
     else:
       yield command, line
   else:
     # All token have been read without errors or early bailout
     assert 'hklf' in self.instructions, "Missing HKLF instruction"
Пример #16
0
 def filtered_commands(self):
   self.label_for_sfac = None
   overall_scale = None
   scatterer_index = 0
   conformer_index = 0
   sym_excl_index = 0
   part_sof = None
   current_residue = (None, None)
   line_of_scatterer_named = {}
   in_the_midst_of_atom_list = False
   idx_assigned_by_builder_to_free_var_idx = {}
   builder = self.builder
   if self.builder_does_occupancy_pair_affine_constraint:
     self.occupancies_depending_on_free_variable = {}
   for command, line in self.command_stream:
     self.line = line
     cmd, args = command[0], command[-1]
     if cmd == 'SFAC':
       builder.make_structure()
       if len(args) == 15 and isinstance(args[1], float):
         raise NotImplementedError(
           '''SFAC label a1 b1 a2 b2 a3 b3 a4 b4 c f' f" mu r wt''')
       self.label_for_sfac = ('*',) + args # (a) working around
                                           #     ShelXL 1-based indexing
     elif cmd == 'FVAR':
       if overall_scale is None:
         overall_scale = args[0]
         self.free_variable = args # (b) ShelXL indexes into the whole array
       else:
         # ShelXL allows for more than one FVAR instruction
         self.free_variable = self.free_variable + args
     elif cmd == 'PART':
       part_sof = None
       conformer_index = 0
       sym_excl_index = 0
       part_number = 0
       if args:
         part_number = int(args[0])
       if len(args) == 2:
         part_sof = self.decode_one_variable(args[1])
       if part_number > 0: conformer_index = part_number
       elif part_number < 0: sym_excl_index = abs(part_number)
     elif cmd == "RESI":
       current_residue = args
       self.builder.add_residue(*current_residue)
     elif cmd == '__ATOM__':
       if not in_the_midst_of_atom_list:
         if self.label_for_sfac is None:
           raise shelx_error("An instruction SFAC needs to appear before "
                             "this point in the file,", self.line)
         in_the_midst_of_atom_list = True
       scatterer, behaviour_of_variable = self.lex_scatterer(
         args, scatterer_index)
       residue_number, residue_class = current_residue
       name = scatterer.label.upper()
       line_1 = line_of_scatterer_named.get((residue_number, name))
       if line_1 is not None:
         raise shelx_error("Residue #%i has two scatterers named %s, "
                           "(with perhaps a difference in letter case)"
                           "defined at lines %i and %i"
                           % (residue_number, name, line, line_1),
                           line=None)
       line_of_scatterer_named[(residue_number, name)] = line
       if (conformer_index or sym_excl_index) and part_sof:
         scatterer.occupancy, behaviour_of_variable[3] = part_sof
       builder.add_scatterer(scatterer, behaviour_of_variable,
                             occupancy_includes_symmetry_factor=True,
                             conformer_index=conformer_index,
                             sym_excl_index=sym_excl_index,
                             residue_number=residue_number,
                             residue_class=residue_class)
       # As the builder accepted the scatterer, we assume that it called
       # scatterer.apply_symmetry so that scatterer.multiplicity and dependents
       # are correctly set. Hence our fetching the scatterer from the builder
       # instead of using the pre-existing local variable.
       scatterer = builder.structure.scatterers()[-1]
       self.process_possible_constrained_occupancy(scatterer_index,
                                                   scatterer,
                                                   behaviour_of_variable[3])
       self.process_possible_u_iso_constraints(scatterer_index,
                                               behaviour_of_variable[4])
       scatterer_index += 1
     elif cmd == '__Q_PEAK__':
       assert not self.strictly_shelxl,\
              "Q-peaks amidst atoms in strict ShelXL model"
       builder.add_electron_density_peak(site = args[2:5],
                                              height = args[-1])
     else:
       yield command, line
   self.process_occupancies_depending_on_free_variable()
Пример #17
0
 def __iter__(self):
     """
 Yields the commands in self.file as tuples:
   - either (cmd, args) where args is a tuple,
     e.g. ('CELL', (0.71073, 1, 2, 3, 90, 90, 90))
   - or (cmd, (residue_class, residue_number), args) for those commands
     which can be suffixed by a residue, e.g.
     ('HFIX', (parser.residue_number_tok, 1), (23, ))
 Notes:
   - For atoms, cmd is '__ATOM__' and the name is the first argument
   - For so-called Q-peaks, cmd is '__Q_PEAK__' and the number is the
     first argument
   - In args, floating point items are reported as is whereas any
     string comes as (type, value) where type is one of the class
     constants defined just above this method (actually, for
     the residue_number_tok, the value is an integer stored as a float).
   - The atomic refinable variables are not decoded: this is the job of
     a parser, not of a lexer.
 """
     continued = False
     for i, li in enumerate(self.file):
         if not li:
             continue
         if continued:
             m = self._continuation_pat.search(li)
             if m is None:
                 raise shelx_error("illegal continuation line error", i)
             cont_args, continued = m.groups()
             arguments.extend(cont_args.split())
         else:
             m = self._cmd_pat.search(li)
             if m is None:
                 if li[0].isspace():
                     continue
                 else:
                     m = self._include_filename_pat.search(li)
                     if m is not None:
                         cmd, filename = m.group(1, 2)
                         yield (cmd, filename), i
                         continue
                 raise shelx_error("illegal command or atom name error", i)
             cmd = m.group(1) or m.group(6)
             if cmd:
                 cmd = cmd.upper()
                 cmd_residue = None
             else:
                 (cmd, cmd_residue_class, cmd_residue_number) = m.group(3, 4, 5)
                 cmd = cmd.upper()
                 if cmd_residue_class:
                     cmd_residue = (tokens.residue_class_tok, cmd_residue_class.upper())
                 elif cmd_residue_number:
                     cmd_residue = (tokens.residue_number_tok, int(cmd_residue_number))
                 else:
                     cmd_residue = (tokens.all_residues_tok,)
             args = m.group(2) or m.group(7) or ""
             continued = m.group(8)
             arguments = args.split()
         if not continued:
             result = self._parse_special_cases(cmd, args, arguments, i, li)
             if result is None:
                 result = self._parse_general_case(cmd, cmd_residue, arguments, i, li)
             yield result, i
             if cmd == "HKLF":
                 break
Пример #18
0
 def parse_restraints(self):
   for cmd, restraints in sorted(self.cached_restraints.items()):
     for line, args in restraints.iteritems():
       cmd_residue = args[0]
       if cmd_residue is None:
         residues = [None]
       else:
         tok = cmd_residue[0]
         if tok == tokens.residue_number_tok:
           residues = [cmd_residue[1]]
         elif tok == tokens.residue_class_tok:
           residues = self.builder.residue_numbers_having_class[cmd_residue[1]]
         elif tok == tokens.all_residues_tok:
           residues = self.builder.residue_class_of_residue_number.keys()
       args = args[1]
       floats = []
       atoms = []
       elements = []
       # it seems that shelxl will accept the restraints and target value/sigma
       # in any order - we will interpret any floating point values as
       # target value (if applicable), sigma, in that order. Any other
       # arguments given are atoms
       for arg in args:
         try:
           floats.append(float(arg))
         except TypeError, e:
           if isinstance(arg, tokens.atomname_token):
             atoms.append(arg)
           elif isinstance(arg, tokens.element_token):
             elements.append(arg)
       for residue_number in residues:
         try:
           i_seqs = self.i_seqs_from_atoms(atoms, residue_number)
           if i_seqs is None: continue
           restraint_type = self.restraint_types.get(cmd)
           if cmd in ('DFIX','DANG'):
             assert len(floats) in (1, 2)
             distance_ideal = floats[0]
             if len(floats) == 2:
               sigma = floats[1]
             else:
               if cmd == 'DFIX': sigma = 0.02
               else: sigma = 0.04
             assert len(atoms) > 1
             weight = 1/(sigma**2)
             assert len(atoms) % 2 == 0
             for i in range(len(atoms)//2):
               atom_pair = atoms[i*2:(i+1)*2]
               i_seq_pair = i_seqs[i*2:(i+1)*2]
               sym_ops = [
                 self.symmetry_operations.get(atom.symmetry)
                 for atom in atom_pair]
               self.builder.process_restraint(restraint_type,
                                              distance_ideal=distance_ideal,
                                              weight=weight,
                                              i_seqs=i_seq_pair,
                                              sym_ops=sym_ops)
           if cmd == 'SADI':
             assert len(floats) <= 1
             if len(floats):
               sigma = floats[0]
             else:
               sigma = 0.02
             i_seq_pairs = []
             sym_ops = []
             for i in range(len(atoms)//2):
               atom_pair = atoms[i*2:(i+1)*2]
               i_seq_pairs.append(i_seqs[i*2:(i+1)*2])
               sym_ops.append(
                 [self.symmetry_operations.get(atom.symmetry)
                  for atom in atom_pair])
             weights = [1/(sigma**2)]*len(i_seq_pairs)
             self.builder.process_restraint(restraint_type,
                                            weights=weights,
                                            i_seqs=i_seq_pairs,
                                            sym_ops=sym_ops)
           elif cmd == 'FLAT':
             assert len(floats) <= 1
             if len(floats) == 1:
               sigma = floats[0]
             else:
               sigma = 0.1
             assert len(atoms) > 3
             sym_ops = [
               self.symmetry_operations.get(atom.symmetry) for atom in atoms]
             weights = [1/(sigma**2)]*len(i_seqs)
             self.builder.process_restraint(restraint_type,
                                            weights=weights,
                                            i_seqs=i_seqs,
                                            sym_ops=sym_ops)
           elif cmd == 'CHIV':
             pass
           elif cmd in ('DELU', 'ISOR', 'SIMU'):
             assert len(floats) <= 3
             s1 = s2 = dmax = None
             if len(floats) > 0:
               s1 = floats[0]
             if len(floats) > 1:
               s2 = floats[1]
             if len(floats) > 2:
               dmax = floats[2]
             if len(i_seqs) == 0:
               i_seqs = None
             if s1 is None:
               if cmd == 'SIMU': s1 = 0.04
               elif cmd == 'DELU': s1 = 0.01
               else: s1 = 0.1
             if cmd == 'DELU':
               self.builder.process_restraint(restraint_type,
                                              sigma_12=s1,
                                              sigma_13=s2,
                                              i_seqs=i_seqs)
             else:
               self.builder.process_restraint(restraint_type,
                                              sigma=s1,
                                              sigma_terminal=s2,
                                              i_seqs=i_seqs)
           else:
             pass
         except (TypeError, AssertionError):
           raise shelx_error("Invalid %s instruction" %cmd, line)
Пример #19
0
 def parse_restraints(self):
   for cmd, restraints in sorted(self.cached_restraints.items()):
     for line, args in restraints.iteritems():
       cmd_residue = args[0]
       if cmd_residue is None:
         residues = [None]
       else:
         tok = cmd_residue[0]
         if tok == tokens.residue_number_tok:
           residues = [cmd_residue[1]]
         elif tok == tokens.residue_class_tok:
           residues = self.builder.residue_numbers_having_class[cmd_residue[1]]
         elif tok == tokens.all_residues_tok:
           residues = self.builder.residue_class_of_residue_number.keys()
       args = args[1]
       floats = []
       atoms = []
       elements = []
       # it seems that shelxl will accept the restraints and target value/sigma
       # in any order - we will interpret any floating point values as
       # target value (if applicable), sigma, in that order. Any other
       # arguments given are atoms
       for arg in args:
         try:
           floats.append(float(arg))
         except TypeError, e:
           if isinstance(arg, tokens.atomname_token):
             atoms.append(arg)
           elif isinstance(arg, tokens.element_token):
             elements.append(arg)
       for residue_number in residues:
         try:
           i_seqs = self.i_seqs_from_atoms(atoms, residue_number)
           if i_seqs is None: continue
           restraint_type = self.restraint_types.get(cmd)
           if cmd in ('DFIX','DANG'):
             assert len(floats) in (1, 2)
             distance_ideal = floats[0]
             if len(floats) == 2:
               sigma = floats[1]
             else:
               if cmd == 'DFIX': sigma = 0.02
               else: sigma = 0.04
             assert len(atoms) > 1
             weight = 1/(sigma**2)
             assert len(atoms) % 2 == 0
             for i in range(len(atoms)//2):
               atom_pair = atoms[i*2:(i+1)*2]
               i_seq_pair = i_seqs[i*2:(i+1)*2]
               sym_ops = [
                 self.symmetry_operations.get(atom.symmetry)
                 for atom in atom_pair]
               self.builder.process_restraint(restraint_type,
                                              distance_ideal=distance_ideal,
                                              weight=weight,
                                              i_seqs=i_seq_pair,
                                              sym_ops=sym_ops)
           if cmd == 'SADI':
             assert len(floats) <= 1
             if len(floats):
               sigma = floats[0]
             else:
               sigma = 0.02
             i_seq_pairs = []
             sym_ops = []
             for i in range(len(atoms)//2):
               atom_pair = atoms[i*2:(i+1)*2]
               i_seq_pairs.append(i_seqs[i*2:(i+1)*2])
               sym_ops.append(
                 [self.symmetry_operations.get(atom.symmetry)
                  for atom in atom_pair])
             weights = [1/(sigma**2)]*len(i_seq_pairs)
             self.builder.process_restraint(restraint_type,
                                            weights=weights,
                                            i_seqs=i_seq_pairs,
                                            sym_ops=sym_ops)
           elif cmd == 'FLAT':
             assert len(floats) <= 1
             if len(floats) == 1:
               sigma = floats[0]
             else:
               sigma = 0.1
             assert len(atoms) > 3
             sym_ops = [
               self.symmetry_operations.get(atom.symmetry) for atom in atoms]
             weights = [1/(sigma**2)]*len(i_seqs)
             self.builder.process_restraint(restraint_type,
                                            weights=weights,
                                            i_seqs=i_seqs,
                                            sym_ops=sym_ops)
           elif cmd == 'CHIV':
             pass
           elif cmd in ('DELU', 'RIGU', 'ISOR', 'SIMU'):
             assert len(floats) <= 3
             s1 = s2 = dmax = None
             if len(floats) > 0:
               s1 = floats[0]
             if len(floats) > 1:
               s2 = floats[1]
             if len(floats) > 2:
               dmax = floats[2]
             if len(i_seqs) == 0:
               i_seqs = None
             if s1 is None:
               if cmd == 'SIMU': s1 = 0.04
               elif cmd == 'DELU': s1 = 0.01
               elif cmd == 'RIGU': s1 = 0.004
               else: s1 = 0.1
             if cmd in ('DELU', 'RIGU'):
               self.builder.process_restraint(restraint_type,
                                              sigma_12=s1,
                                              sigma_13=s2,
                                              i_seqs=i_seqs)
             else:
               self.builder.process_restraint(restraint_type,
                                              sigma=s1,
                                              sigma_terminal=s2,
                                              i_seqs=i_seqs)
           else:
             pass
         except (TypeError, AssertionError):
           raise shelx_error("Invalid %s instruction" %cmd, line)
Пример #20
0
 def raise_parameter_error():
   raise shelx_error(
     "scatterer parameter #%d '%s'", line, i_cv+1, coded_variable)