diff --git a/geminidr/__init__.py b/geminidr/__init__.py index 337e43d0e..df2e80923 100644 --- a/geminidr/__init__.py +++ b/geminidr/__init__.py @@ -275,7 +275,10 @@ def find_similar_names(name, valid_names): if primitive: alternative_primitives = find_similar_names(primitive, self.params.keys()) if alternative_primitives is None: # it's valid - alternative_parameters = find_similar_names(parameter, self.params[primitive]) + if parameter in ('skip_primitive', 'write_outputs'): + alternative_parameters = None + else: + alternative_parameters = find_similar_names(parameter, self.params[primitive]) else: alternative_parameters = find_similar_names( parameter, chain(*[v.keys() for v in self.params.values()])) diff --git a/recipe_system/utils/decorators.py b/recipe_system/utils/decorators.py index 2950a12d1..42e7e5173 100644 --- a/recipe_system/utils/decorators.py +++ b/recipe_system/utils/decorators.py @@ -317,44 +317,59 @@ def gn(pobj, *args, **kwargs): instream = params.get('instream', stream) outstream = params.get('outstream', stream) adinputs = params.get('adinputs') - for k in ('adinputs', 'stream', 'instream', 'outstream'): - if k not in config: - with suppress(KeyError): - del params[k] - # Can update config now it only has parameters it knows about - config.update(**params) - config.validate() - - if len(args) == 0 and adinputs is None: - # Use appropriate stream input/output - # Many primitives operate on AD instances in situ, so need to - # copy inputs if they're going to a new output stream + skip = params.get('skip_primitive', False) + write_after = params.get('write_outputs', False) and toplevel + + if skip and toplevel: + log.stdinfo(f"Parameter skip_primitive has been set so {pname} " + "will not be run") if instream != outstream: - adinputs = [deepcopy(ad) for ad in pobj.streams.get(instream, [])] - else: - # Allow a non-existent stream to be passed - adinputs = pobj.streams.get(instream, []) - - try: - fnargs = dict(config.items()) - ret_value = fn(pobj, adinputs=adinputs, **fnargs) - except Exception: - zeroset() - raise - # And place the outputs in the appropriate stream - pobj.streams[outstream] = ret_value + log.warning("The input and output streams differ so skipping " + "this primitive may have unintended consequences") + ret_value = pobj.streams[instream] else: - if args: # if not, adinputs has already been assigned from params - adinputs = args[0] - - try: - if isinstance(adinputs, AstroData): - raise TypeError("Single AstroData instance passed to " - "primitive, should be a list") - ret_value = fn(pobj, adinputs=adinputs, **dict(config.items())) - except Exception: - zeroset() - raise + for k in ('adinputs', 'stream', 'instream', 'outstream', + 'skip_primitive', 'write_outputs'): + if k not in config: + with suppress(KeyError): + del params[k] + # Can update config now it only has parameters it knows about + config.update(**params) + config.validate() + + if len(args) == 0 and adinputs is None: + # Use appropriate stream input/output + # Many primitives operate on AD instances in situ, so need to + # copy inputs if they're going to a new output stream + if instream != outstream: + adinputs = [deepcopy(ad) for ad in pobj.streams.get(instream, [])] + else: + # Allow a non-existent stream to be passed + adinputs = pobj.streams.get(instream, []) + + try: + fnargs = dict(config.items()) + ret_value = fn(pobj, adinputs=adinputs, **fnargs) + except Exception: + zeroset() + raise + # And place the outputs in the appropriate stream + pobj.streams[outstream] = ret_value + else: + if args: # if not, adinputs has already been assigned from params + adinputs = args[0] + + try: + if isinstance(adinputs, AstroData): + raise TypeError("Single AstroData instance passed to " + "primitive, should be a list") + ret_value = fn(pobj, adinputs=adinputs, **dict(config.items())) + except Exception: + zeroset() + raise + + if write_after: + pobj.writeOutputs(stream=outstream) unset_logging() gc.collect() return ret_value