Changeset 3215 for trunk

Show
Ignore:
Timestamp:
12/09/11 11:05:35 (6 months ago)
Author:
jos
Message:

Add -M for multi dimensional scanning

Location:
trunk/src/mcrun2
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/mcrun2/main.py

    r3210 r3215  
    1010 
    1111from mcstas import McStas 
    12 from optimisation import Scanner, LinearInterval 
     12from optimisation import Scanner, LinearInterval, MultiInterval 
    1313 
    1414LOG = logging.getLogger('mcstas') 
     
    5353        action='store_true', 
    5454        help='use a fixed list of points for linear scanning') 
     55 
     56    add('-M', '--multi', 
     57        action='store_true', 
     58        help='run a multi-dimensional scan') 
    5559 
    5660    # Multiprocessing 
     
    276280 
    277281    # Check for linear scanning 
    278     linear_interval = None 
     282    interval_points = None 
    279283 
    280284    # Can't both do list and interval scanning 
     
    282286        raise OptionValueError('--numpoints cannot be used with --list') 
    283287 
    284     elif options.list: 
     288    if options.list: 
    285289        if len(intervals) == 0: 
    286290            raise OptionValueError( 
     
    290294            raise OptionValueError( 
    291295                'All variables much have an equal amount of points.') 
    292         linear_interval = LinearInterval.from_list( 
     296        interval_points = LinearInterval.from_list( 
    293297            points, intervals) 
    294298 
    295     elif options.numpoints is not None: 
    296         if options.numpoints < 2: 
    297             raise OptionValueError( 
    298                 ('Cannot scan variable(s) %s using only one data point. ' 
    299                  'Please use -N to specify the number of points.') % \ 
    300                 ', '.join(intervals.keys())) 
     299    scan = options.multi or options.numpoints 
     300    if ((options.numpoints is not None and options.numpoints < 2) 
     301        or (scan and options.numpoints is None)): 
     302        raise OptionValueError( 
     303            ('Cannot scan variable(s) %s using only one data point. ' 
     304             'Please use -N to specify the number of points.') % \ 
     305            ', '.join(intervals.keys())) 
    301306        # Check that input is valid decimals 
    302307        if not all(map(lambda i: 
     
    306311                                   % str(intervals)) 
    307312 
    308         linear_interval = LinearInterval.from_range( 
     313    if options.multi is not None: 
     314        interval_points = MultiInterval.from_range( 
    309315            options.numpoints, intervals) 
    310316 
     317    elif options.numpoints is not None: 
     318        interval_points = LinearInterval.from_range( 
     319            options.numpoints, intervals) 
     320 
    311321    # Parameters for linear scanning present 
    312     if linear_interval: 
     322    if interval_points: 
    313323        scanner = Scanner(mcstas, intervals) 
    314         scanner.set_points(linear_interval) 
     324        scanner.set_points(interval_points) 
    315325        scanner.run() 
    316326    else: 
  • trunk/src/mcrun2/optimisation.py

    r3210 r3215  
    7171 
    7272 
     73def point_at(N, key, minmax, step): 
     74    """ Helper to compute the point for key at step """ 
     75    low, high = map(Decimal, minmax) 
     76    return step * (high - low) / Decimal(N - 1) + low 
     77 
     78 
    7379class LinearInterval: 
    7480    """ Intervals for linear scanning """ 
     
    7682    @staticmethod 
    7783    def from_range(N, intervals): 
    78  
    79         def point_at(key, step): 
    80             low, high = map(Decimal, intervals[key]) 
    81             return step * (high - low) / Decimal(N - 1) + low 
    82  
    8384        for step in xrange(N): 
    84             yield dict((key, point_at(key, step)) for key in intervals) 
     85            yield dict((key, point_at(N, key, intervals[key], step)) 
     86                       for key in intervals) 
    8587 
    8688    @staticmethod 
     
    8890        for step in xrange(N): 
    8991            yield dict((key, intervals[key][step]) for key in intervals) 
     92 
     93 
     94class MultiInterval: 
     95    """ Points for multi-dimensional scanning """ 
     96 
     97    @staticmethod 
     98    def from_range(N, intervals): 
     99        # base case: no intervals yields empty dict 
     100        if len(intervals) == 0: 
     101            yield {} 
     102            return 
     103        # recursively generate the multi dict 
     104        intervals = intervals.copy() 
     105        key, minmax = intervals.popitem() 
     106        for step in xrange(N): 
     107            point = point_at(N, key, minmax, step) 
     108            for dic in MultiInterval.from_range(N, intervals): 
     109                dic[key] = point 
     110                yield dic 
    90111 
    91112