Changeset 303d8d6 in sasmodels for sasmodels/generate.py
- Timestamp:
- Mar 21, 2016 12:49:21 AM (8 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 4a72d1a, 3a45c2c
- Parents:
- 03cac08
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/generate.py
r03cac08 r303d8d6 354 354 return [_search(search_path, f) for f in model_info['source']] 355 355 356 357 356 def convert_type(source, dtype): 358 357 """ … … 419 418 if filename not in _template_cache or mtime > _template_cache[filename][0]: 420 419 with open(path) as fid: 421 _template_cache[filename] = (mtime, fid.read() )420 _template_cache[filename] = (mtime, fid.read(), path) 422 421 return _template_cache[filename][1] 422 423 def model_templates(): 424 # TODO: fails DRY; templates are listed in two places. 425 # should instead have model_info contain a list of paths 426 return [joinpath(TEMPLATE_ROOT, filename) 427 for filename in ('kernel_header.c', 'kernel_iq.c')] 428 423 429 424 430 _FN_TEMPLATE = """\ … … 450 456 """ 451 457 prefix += "." 452 return [prefix+p .namefor p in pars]458 return [prefix+p for p in pars] 453 459 454 460 _IQXY_PATTERN = re.compile("^((inline|static) )? *(double )? *Iqxy *([(]|$)", … … 513 519 # Generate form_volume function, etc. from body only 514 520 if model_info['form_volume'] is not None: 515 pnames = [p .namefor p in vol_parameters]521 pnames = [p for p in vol_parameters] 516 522 source.append(_gen_fn('form_volume', pnames, model_info['form_volume'])) 517 523 if model_info['Iq'] is not None: 518 pnames = ['q'] + [p .namefor p in iq_parameters]524 pnames = ['q'] + [p for p in iq_parameters] 519 525 source.append(_gen_fn('Iq', pnames, model_info['Iq'])) 520 526 if model_info['Iqxy'] is not None: 521 pnames = ['qx', 'qy'] + [p .namefor p in iqxy_parameters]527 pnames = ['qx', 'qy'] + [p for p in iqxy_parameters] 522 528 source.append(_gen_fn('Iqxy', pnames, model_info['Iqxy'])) 523 529 … … 552 558 553 559 # Fill in definitions for numbers of parameters 554 source.append("#define MAX_PD %s"% MAX_PD)560 source.append("#define MAX_PD %s"%model_info['max_pd']) 555 561 source.append("#define NPARS %d"%(len(model_info['parameters'])-2)) 556 562 … … 584 590 * *magnetic* set of parameters that are used to compute magnetic 585 591 patterns (which includes all 1D and 2D parameters) 586 * *sesans* set of parameters that are used to compute sesans patterns 587 (which is just 1D without background) 588 * *pd-relative* is the set of parameters with relative distribution 592 * *pd_relative* is the set of parameters with relative distribution 589 593 width (e.g., radius +/- 10%) rather than absolute distribution 590 594 width (e.g., theta +/- 6 degrees). 591 595 """ 592 596 par_set = {} 593 par_set['1d'] = [p for p in pars if p.type not in ('orientation', 'magnetic')]594 par_set['2d'] = [p for p in pars if p.type != 'magnetic']595 par_set['magnetic'] = [p for p in pars]596 par_set['pd'] = [p for p in pars if p.type in ('volume', 'orientation')]597 par_set['pd_relative'] = [p for p in pars if p.type == 'volume']597 par_set['1d'] = [p.name for p in pars if p.type not in ('orientation', 'magnetic')] 598 par_set['2d'] = [p.name for p in pars if p.type != 'magnetic'] 599 par_set['magnetic'] = [p.name for p in pars] 600 par_set['pd'] = [p.name for p in pars if p.type in ('volume', 'orientation')] 601 par_set['pd_relative'] = [p.name for p in pars if p.type == 'volume'] 598 602 return par_set 599 603 … … 621 625 } 622 626 for p in pars: 623 par_type[p.type if p.type else 'other'].append(p )627 par_type[p.type if p.type else 'other'].append(p.name) 624 628 return par_type 625 629 … … 641 645 par_type.update(categorize_parameters(pars)) 642 646 model_info['parameters'] = pars 643 model_info['limits'] = dict((p.name, p.limits) for p in pars)644 647 model_info['par_type'] = par_type 645 model_info['defaults'] = dict((p.name, p.default) for p in pars)646 648 if model_info.get('demo', None) is None: 647 model_info['demo'] = model_info['defaults']649 model_info['demo'] = dict((p.name, p.default) for p in pars) 648 650 model_info['has_2d'] = par_type['orientation'] or par_type['magnetic'] 651 652 def mono_details(max_pd, npars): 653 par_offset = 5*max_pd 654 const_offset = par_offset + 3*npars 655 656 mono = np.zeros(const_offset + 3, 'i') 657 mono[0] = 0 # pd_par: arbitrary order; use first 658 mono[1*max_pd] = 1 # pd_length: only one element 659 mono[2*max_pd] = 2 # pd_offset: skip scale and background 660 mono[3*max_pd] = 1 # pd_stride: vectors of length 1 661 mono[4*max_pd-1] = 1 # pd_stride[-1]: only one element in set 662 mono[4*max_pd] = 0 # pd_isvol: doens't matter if no norm 663 mono[par_offset:par_offset+npars] = np.arange(2, npars+2, dtype='i') 664 # par_offset: copied in order 665 mono[par_offset+npars:par_offset+2*npars] = 0 666 # par_coord: no coordinated parameters 667 mono[par_offset+npars] = 1 # par_coord[0]: except par 0 668 mono[par_offset+2*npars:par_offset+3*npars] = 0 669 # fast coord with 0 670 mono[const_offset] = 1 # fast_coord_count: one fast index 671 mono[const_offset+1] = -1 # theta_var: None 672 mono[const_offset+2] = 0 # fast_theta: False 673 return mono 674 675 def poly_details(model_info, weights, pars, constraints=None): 676 if constraints is not None: 677 # Need to find the independently varying pars and sort them 678 # Need to build a coordination list for the dependent variables 679 # Need to generate a constraints function which takes values 680 # and weights, returning par blocks 681 raise ValueError("Can't handle constraints yet") 682 683 raise ValueError("polydispersity not supported") 684 649 685 650 686 def create_default_functions(model_info): … … 688 724 model variants (e.g., the list of cases) or is None if there are no 689 725 model variants 690 * *defaults* is the *{parameter: value}* table built from the parameter 691 description table. 692 * *limits* is the *{parameter: [min, max]}* table built from the 693 parameter description table. 694 * *partypes* categorizes the model parameters. See 726 * *par_type* categorizes the model parameters. See 695 727 :func:`categorize_parameters` for details. 696 728 * *demo* contains the *{parameter: value}* map used in compare (and maybe … … 709 741 *model_info* blocks for the composition objects. This allows us to 710 742 build complete product and mixture models from just the info. 743 * *max_pd* is the max polydispersity dimension. This is constant and 744 should not be reset. You may be able to change it when the program 745 starts by setting *sasmodels.generate.MAX_PD*. 711 746 712 747 """ … … 719 754 name = " ".join(w.capitalize() for w in kernel_id.split('_')) 720 755 model_info = dict( 756 max_pd=MAX_PD, 721 757 id=kernel_id, # string used to load the kernel 722 758 filename=abspath(kernel_module.__file__), … … 736 772 oldpars=getattr(kernel_module, 'oldpars', {}), 737 773 tests=getattr(kernel_module, 'tests', []), 774 mono_details = mono_details(MAX_PD, len(kernel_module.parameters)) 738 775 ) 739 776 process_parameters(model_info)
Note: See TracChangeset
for help on using the changeset viewer.