Editing
Tutorial
(section)
Jump to navigation
Jump to search
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Advanced SCons== Now that you have a grasp of how to use SCons to put together simple processing flows, we're going to show you how to abuse SCons to make more advanced processing flows that can handle multiple input and output files properly. Additionally, we're going to demonstrate some SCons tricks that make your life easier, and allow you to work faster, and smarter. ===Multiple input files=== Many Madagascar programs require multiple input files and/or output multiple files. In order for SCons to properly recognize that these additional files are dependencies for a specific output file we have to change the syntax that we use for '''Flow''' , '''Plot''' and '''Result''' statements. To do so, we'll need to use Python lists to help us keep everything together when using our SCons commands. We first discuss the case where we need multiple input files. An example of a Madagascar program that requires multiple input files is '''sfcat''' . For reference, sfcat is used to concatenate multiple files together, essentially a file manipulation program. For example, we might use sfcat on the command line in the following fashion: <pre> < file.rsf sfcat axis=2 file1.rsf file2.rsf file3.rsf file4.rsf > catted.rsf </pre> To replicate this behavior using SCons we need to tell our '''Flow''' statements about the presence of multiple input files. '''Important: if we do not indicate to SCons that we have multiple input files then the dependency chain will not be correct and we cannot guarantee our results are correct''' . We can easily tell SCons of the presence of multiple input files by using a Python list as our input file, instead of a string: <syntaxhighlight lang="python"> Flow('catted',['file','file1','file2','file3','file4'],'sfcat axis=2 ${SOURCES[1:-1]}') </syntaxhighlight> or, equivalently, <syntaxhighlight lang="python"> Flow('catted','file file1 file2 file3 file4','sfcat axis=2 ${SOURCES[1:-1]}') </syntaxhighlight> As you may have noticed, there are two new items in this '''Flow''' statement, but let's start by discussing only the list of file names: '''['file','file1','file2','file3','file4']''' . The list of file names is simply a Python list of strings that contains each of the names of the files that we want to use in this Flow command. As usual, we don't have to append the '.rsf' suffix to the end of these names because SCons adds it for us. The second new part to the '''Flow''' command is: '''${SOURCES[1:-1]''' }, referred to as the SCons source list, which tells SCons about the presence of additional input files in the command, and to substitute the names into the command automatically. Without this command, SCons would not include the files in the final command. As an example of what the SCons source list does, compare the two SConstructs below against one another. The top is correct, the bottom is incorrectly configured: <syntaxhighlight lang="python"> # Correct from rsf.proj import * Flow('file',None,'spike n1=100') Flow('file1',None,'spike n1=100 mag=2') Flow('file2',None,'spike n1=100 mag=3') Flow('file3',None,'spike n1=100 mag=4') Flow('file4',None,'spike n1=100 mag=5') Flow('catted',['file','file1','file2','file3','file4'], 'sfcat axis=2 ${SOURCES[1:-1]}') End() </syntaxhighlight> <syntaxhighlight lang="python"> # Wrong from rsf.proj import * Flow('file',None,'spike n1=100') Flow('file1',None,'spike n1=100') Flow('file2',None,'spike n1=100') Flow('file3',None,'spike n1=100') Flow('file4',None,'spike n1=100') Flow('catted',['file','file1','file2','file3','file4'],'sfcat axis=2') End() </syntaxhighlight> If you noticed the command line output from SCons, you would find that for the incorrect SConstruct, SCons ran the following command: <pre> < file.rsf sfcat axis=2 > catted.rsf </pre> which is not correct. This is because SCons was not informed that the additional sources actually are used inside the command and did not substitute them in. The SCons source list contains a reference to all of the file names that we passed in our Python list earlier. In order to access those names we have to use a specific notation, but it is essentially a Python list enclosed in curly brackets that begins with a $. Since the source list is a Python list, we can get the file names in a few ways if we follow standard Python list conventions. Standard Python list conventions are: *List indexing starts with index 0, *Lists may be negatively indexed, which returns the items from the end (e.g. LIST[-1]), *Lists may be sliced using the LIST[start:end] notation, where start and end are indices, *List slicing indices are inclusive for the starting index, and exclusive for the ending index (e.g. LIST[0:4] returns LIST[0],LIST[1],LIST[2],LIST[3] but NOT LIST[4], *Open slicing indices may be used (e.g. LIST[2:] gets everything from index 2 to the end, and LIST[:4] returns everything from 0 to but not including 4). *Negative and positive indices may be used together (e.g. LIST[1:-1] returns all elements but the first and last). These are the most useful conventions to remember, and the ones you will most frequently see. Please see the Python documentation (freely available online) for more information about dealing with Lists. Using the above conventions the following '''Flow''' statements are all equivalent for lettings SCons know about the presence of multiple input files: <syntaxhighlight lang="python"> Flow('catted',['file','file1','file2','file3','file4'], ''' sfcat axis=2 ${SOURCES[1]} ${SOURCES[2]} ${SOURCES[3]} ${SOURCES[4]} ''') Flow('catted',['file','file1','file2','file3','file4'], ''' sfcat axis=2 ${SOURCES[1:5]} ''') Flow('catted',['file','file1','file2','file3','file4'], ''' sfcat axis=2 ${SOURCES[1:-1]} ''') </syntaxhighlight> Note: never use SOURCES[0] because SOURCES[0] corresponds to 'file' which is already used by SCons for standard input. Also, never use open slicing on the SOURCES list, because at the end of the SOURCES list are extra items added by SCons for safe keeping that will break the command if accidentally used. ===Multiple outputs=== For multiple outputs, we can use the same conventions as before, except we specify a list of output files instead of input files, and we use the TARGETS SCons list, instead of SOURCES. For example: <syntaxhighlight lang="python"> Flow(['pef','lag'], 'dat', 'sflpef lag=${TARGETS[1]}'). </syntaxhighlight> ===None inputs=== Sometimes, '''Flow''' s are created that don't have an input file. For example, files created using '''sfspike''' do not require input files. To get around the need for an input file, we can use the Python keyword '''None''' , equivalent to NULL in C or Java, to indicate to SCons that no input file is needed. For example: <syntaxhighlight lang="python"> Flow('spike',None,'sfspike n1=100') </syntaxhighlight> ===Toggling standard input and standard output=== When None inputs are used, then standard input is no longer needed and can be disabled. To turn off standard input on a '''Flow''' , add another argument to the '''Flow''' statement: <syntaxhighlight lang="python"> Flow('spike',None,'sfspike n1=100',stdin=0) </syntaxhighlight> When SCons runs this '''Flow''' , the output command line will be: <pre> sfspike n1=100 > spike.rsf </pre> Likewise, we can toggle output to standard output as well. Standard output has two options, redirect to null or completely off. For some programs we need to redirect standard output to null, and others will require standard output to be completely off. To toggle standard output off use the following syntax: <syntaxhighlight lang="python"> Flow('spike',None,'sfspike n1=100',stdout=-1) </syntaxhighlight> OR to redirect to <tt>/dev/null</tt>: <syntaxhighlight lang="python"> Flow('spike',None,'sfspike n1=100',stdout=0) </syntaxhighlight> ===Plots with a different output name=== Occasionally, you might want to create a plot with a different name than the input file. For example, a file might have multiple axes, and you could window along one of the axes, to create multiple graphs from a single input file. To distinguish between the different plots, you can rename the output files from Plot and Result commands using a syntax similar to Flow: <syntaxhighlight lang="python"> Plot('output','input','sfgraph') </syntaxhighlight> This Plot command will produce output.vpl instead of input.vpl. In this way, you can create multiple visualizations of the same file. This applies to Result commands as well.
Summary:
Please note that all contributions to Madagascar are considered to be released under the GNU Free Documentation License 1.3 or later (see
My wiki:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Navigation menu
Personal tools
English
Not logged in
Talk
Contributions
Create account
Log in
Namespaces
Page
Discussion
English
Views
Read
Edit
View history
More
Search
Getting Madagascar
download
Installation
GitHub repository
SEGTeX
Introduction
Package overview
Tutorial
Hands-on tour
Reproducible documents
Hall of Fame
User Documentation
List of programs
Common programs
Popular programs
The RSF file format
Reproducibility with SCons
Developer documentation
Adding programs
Contributing programs
API demo: clipping data
API demo: explicit finite differences
Community
Conferences
User mailing list
Developer mailing list
GitHub organization
LinkedIn group
Development blog
Twitter
Slack
Tools
What links here
Related changes
Special pages
Page information