It is the year 953 A.D. and Sufi23 is in Shiraz as a guest astronomer. He had come there to use the advanced 123 centimeter astrolabe for his studies on the Ecliptic. However, something was bothering him for a long time. While mapping the constellations, there were several non-stellar objects that he had detected in the sky, one of them was in the Andromeda constellation. During a trip he had to Yemen, Sufi had seen another such object in the southern skies looking over the Indian ocean. He wasn’t sure if such cloud-like non-stellar objects (which he was the first to call ‘Sahābi’ in Arabic or ‘nebulous’) were real astronomical objects or if they were only the result of some bias in his observations. Could such diffuse objects actually be detected at all with his detection technique?
He still had a few hours left until nightfall (when he would continue his studies on the ecliptic) so he decided to find an answer to this question. He had thoroughly studied Claudius Ptolemy’s (90 – 168 A.D) Almagest and had made lots of corrections to it, in particular in measuring the brightness. Using his same experience, he was able to measure a magnitude for the objects and wanted to simulate his observation to see if a simulated object with the same brightness and size could be detected in a simulated noise with the same detection technique. The general outline of the steps he wants to take are:
Fortunately Sufi had heard of GNU Astronomy Utilities from a colleague in Isfahan (where he worked) and had installed it on his computer a year before. It had tools to do all the steps above. He had used MakeProfiles before, but wasn’t sure which columns he had chosen in his user or system wide configuration files for which parameters, see Configuration files. So to start his simulation, Sufi runs MakeProfiles with the -P option to make sure what columns in a catalog MakeProfiles currently recognizes and the output image parameters. In particular, Sufi is interested in the recognized columns (shown below).
$ astmkprof -P [[[ ... Truncated lines ... ]]] # Output: type float32 # Type of output: e.g., int16, float32, etc... naxis 1000,1000 # Number of pixels along first FITS axis. oversample 5 # Scale of oversampling (>0 and odd). [[[ ... Truncated lines ... ]]] # Columns, by info (see `--searchin'), or number (starting from 1): ccol 2 # Center along first FITS axis (horizontal). ccol 3 # Center along second FITS axis (vertical). fcol 4 # sersic (1), moffat (2), gaussian (3), # point (4), flat (5), circumference (6). rcol 5 # Effective radius or FWHM in pixels. ncol 6 # Sersic index or Moffat beta. pcol 7 # Position angle. qcol 8 # Axis ratio. mcol 9 # Magnitude. tcol 10 # Truncation in units of radius or pixels. [[[ ... Truncated lines ... ]]]
In Gnuastro, column counting starts from 1, so the columns are ordered such that the first column (number 1) can be an ID he specifies for each object (and MakeProfiles ignores), each subsequent column is used used for another property of the profile. It is also possible to use column names for the values of these options and change these defaults, but Sufi preferred to stick to the defaults. Fortunately MakeProfiles has the capability to also make the PSF which is to be used on the mock image and using the --prepforconv option, he can also make the mock image to be larger by the correct amount and all the sources to be shifted by the correct amount.
For his initial check he decides to simulate the nebula in the Andromeda
constellation. The night he was observing, the PSF had roughly a FWHM of
about 5 pixels, so as the first row (profile), he defines the PSF
parameters and sets the radius column (
rcol above, fifth column) to
5.000, he also chooses a Moffat function for its functional
form. Remembering how diffuse the nebula in the Andromeda constellation
was, he decides to simulate it with a mock Sérsic index 1.0 profile. He
wants the output to be 500 pixels by 500 pixels, so he puts the mock
profile in the center. Looking at his drawings of it, he decides a
reasonable effective radius for it would be 40 pixels on this image pixel
scale, he sets the axis ratio and position angle to approximately correct
values too and finally he sets the total magnitude of the profile to 3.44
which he had accurately measured. Sufi also decides to truncate both the
mock profile and PSF at 5 times the respective radius parameters. In the
end he decides to put four stars on the four corners of the image at very
low magnitudes as a visual scale.
Using all the information above, he creates the catalog of mock profiles he
wants in a file named cat.txt (short for catalog) using his favorite
text editor and stores it in a directory named simulationtest in his
home directory. [The
cat command prints the contents of a file,
short for concatenation. So please copy-paste the lines after
cat cat.txt” into cat.txt when the editor opens in the
steps above it, note that there are 7 lines, first one starting with
$ mkdir ~/simulationtest $ cd ~/simulationtest $ pwd /home/rahman/simulationtest $ emacs cat.txt $ ls cat.txt $ cat cat.txt # Column 4: PROFILE_NAME [,str7] Radial profile's functional name 1 0.0000 0.0000 moffat 5.000 4.765 0.0000 1.000 30.000 5.000 2 250.00 250.00 sersic 40.00 1.000 -25.00 0.400 3.4400 5.000 3 50.000 50.000 point 0.000 0.000 0.0000 0.000 9.0000 0.000 4 450.00 50.000 point 0.000 0.000 0.0000 0.000 9.2500 0.000 5 50.000 450.00 point 0.000 0.000 0.0000 0.000 9.5000 0.000 6 450.00 450.00 point 0.000 0.000 0.0000 0.000 9.7500 0.000
The zero-point magnitude for his observation was 18. Now he has all the necessary parameters and runs MakeProfiles with the following command:
$ astmkprof --prepforconv --naxis=500,500 --zeropoint=18.0 cat.txt MakeProfiles started on Sat Oct 6 16:26:56 953 - 6 profiles read from cat.txt - Random number generator (RNG) type: mt19937 - Using 8 threads. ---- row 2 complete, 5 left to go ---- row 3 complete, 4 left to go ---- row 4 complete, 3 left to go ---- row 5 complete, 2 left to go ---- ./0_cat.fits created. ---- row 0 complete, 1 left to go ---- row 1 complete, 0 left to go - ./cat.fits created. 0.041651 seconds MakeProfiles finished in 0.267234 seconds $ls 0_cat.fits cat.fits cat.txt
The file 0_cat.fits is the PSF Sufi had asked for and cat.fits is the image containing the other 5 objects. The PSF is now available to him as a separate file for the convolution step. While he was preparing the catalog, one of his students approached him and was also following the steps. When he opened the image, the student was surprised to see that all the stars are only one pixel and not in the shape of the PSF as we see when we image the sky at night. So Sufi explained to him that the stars will take the shape of the PSF after convolution and this is how they would look if we didn’t have an atmosphere or an aperture when we took the image. The size of the image was also surprising for the student, instead of 500 by 500, it was 2630 by 2630 pixels. So Sufi had to explain why oversampling is important for parts of the image where the flux change is significant over a pixel. Sufi then explained to him that after convolving we will re-sample the image to get our originally desired size. To convolve the image, Sufi ran the following command:
$ astconvolve --kernel=0_cat.fits cat.fits Convolve started on Mon Apr 6 16:35:32 953 - Using 8 CPU threads. - Input: cat.fits (hdu: 1) - Kernel: 0_cat.fits (hdu: 1) - Input and Kernel images padded. 0.075541 seconds - Images converted to frequency domain. 6.728407 seconds - Multiplied in the frequency domain. 0.040659 seconds - Converted back to the spatial domain. 3.465344 seconds - Padded parts removed. 0.016767 seconds Convolve finished in: 10.422161 seconds $ls 0_cat.fits cat_convolved.fits cat.fits cat.txt
When convolution finished, Sufi opened the cat_convolved.fits file
and showed the effect of convolution to his student and explained to him
how a PSF with a larger FWHM would make the points even wider. With the
convolved image ready, they were prepared to re-sample it to the original
pixel scale Sufi had planned [from the
$ astmkprof -P command
above, recall that MakeProfiles had over-sampled the image by 5 times]. Sufi
explained the basic concepts of warping the image to his student and ran
Warp with the following command:
$ astwarp --scale=1/5 --centeroncorner cat_convolved.fits Warp started on Mon Apr 6 16:51:59 953 Using 8 CPU threads. Input: cat_convolved.fits (hdu: 1) matrix: 0.2000 0.0000 0.4000 0.0000 0.2000 0.4000 0.0000 0.0000 1.0000 $ ls 0_cat.fits cat_convolved_scaled.fits cat.txt cat_convolved.fits cat.fits $ astfits -p cat_convolved_scaled.fits | grep NAXIS NAXIS = 2 / number of data axes NAXIS1 = 526 / length of data axis 1 NAXIS2 = 526 / length of data axis 2
cat_convolved_warped.fits now has the correct pixel scale. However, the image is still larger than what we had wanted, it is 526 (\(500+13+13\)) by 526 pixels. The student is slightly confused, so Sufi also re-samples the PSF with the same scale and shows him that it is 27 (\(2\times13+1\)) by 27 pixels. Sufi goes on to explain how frequency space convolution will dim the edges and that is why he added the --prepforconv option to MakeProfiles, see If convolving afterwards. Now that convolution is done, Sufi can remove those extra pixels using Crop with the command below. Crop’s --section option accepts coordinates inclusively and counting from 1 (according to the FITS standard), so the crop’s first pixel has to be 14, not 13.
$ astcrop cat_convolved_scaled.fits --section=14:*-13,14:*-13 \ --zeroisnotblank Crop started on Sat Oct 6 17:03:24 953 - Read metadata of 1 image. 0.001304 seconds ---- ...nvolved_scaled_cropped.fits created: 1 input. Crop finished in: 0.027204 seconds $ls 0_cat.fits cat_convolved_scaled_cropped.fits cat.fits cat_convolved.fits cat_convolved_scaled.fits cat.txt
Finally, cat_convolved_scaled_cropped.fits has the same dimensions as Sufi had desired in the beginning. All this trouble was certainly worth it because now there is no dimming on the edges of the image and the profile centers are more accurately sampled. The final step to simulate a real observation would be to add noise to the image. Sufi set the zeropoint magnitude to the same value that he set when making the mock profiles and looking again at his observation log, he had measured the background flux near the nebula had a magnitude of 7 that night. So using these values he ran MakeNoise:
$ astmknoise --zeropoint=18 --background=7 --output=out.fits \ cat_convolved_warped_crop.fits MakeNoise started on Mon Apr 6 17:05:06 953 - Generator type: mt19937 - Generator seed: 1428318100 MakeNoise finished in: 0.033491 (seconds) $ls 0_cat.fits cat_convolved_scaled_cropped.fits cat.fits out.fits cat_convolved.fits cat_convolved_scaled.fits cat.txt
The out.fits file now contains the noised image of the mock catalog Sufi had asked for. Seeing how the --output option allows the user to specify the name of the output file, the student was confused and wanted to know why Sufi hadn’t used it before? Sufi then explained to him that for intermediate steps it is best to rely on the automatic output, see Automatic output. Doing so will give all the intermediate files the same basic name structure, so in the end you can simply remove them all with the Shell’s capabilities. So Sufi decided to show this to the student by making a shell script from the commands he had used before.
The command-line shell has the capability to read all the separate input
commands from a file. This is useful when you want to do the same thing
multiple times, with only the names of the files or minor parameters
changing between the different instances. Using the shell’s history (by
pressing the up keyboard key) Sufi reviewed all the commands and then he
retrieved the last 5 commands with the
$ history 5 command. He
selected all those lines he had input and put them in a text file named
mymock.sh. Then he defined the
variables for easier customization later. Finally, before every command, he
added some comments (lines starting with #) for future readability.
# Basic settings: edge=13 base=cat # Remove any existing image to avoid confusion. rm out.fits # Run MakeProfiles to create an oversampled FITS image. astmkprof --prepforconv --naxis=500,500 --zeropoint=18.0 "$base".txt # Convolve the created image with the kernel. astconvolve --kernel=0_"$base".fits "$base".fits # Scale the image back to the intended resolution. astwarp --scale=1/5 --centeroncorner "$base"_convolved.fits # Crop the edges out (dimmed during convolution). `--section' accepts # inclusive coordinates, so the start of start of the section must be # one pixel larger than its end. st_edge=$(( edge + 1 )) astcrop "$base"_convolved_scaled.fits --zeroisnotblank \ --section=$st_edge:*-$edge,$st_edge:*-$edge # Add noise to the image. astmknoise --zeropoint=18 --background=7 --output=out.fits \ "$base"_convolved_scaled_cropped.fits # Remove all the temporary files. rm 0*.fits cat*.fits
He used this chance to remind the student of the importance of comments in code or shell scripts: when writing the code, you have a good mental picture of what you are doing, so writing comments might seem superfluous and excessive. However, in one month when you want to re-use the script, you have lost that mental picture and rebuilding it is can be time-consuming and frustrating. The importance of comments is further amplified when you want to share the script with a friend/colleague. So it is good to accompany any script/code with useful comments while you are writing it (have a good mental picture of what/why you are doing something).
Sufi then explained to the eager student that you define a variable by
giving it a name, followed by an
= sign and the value you
want. Then you can reference that variable from anywhere in the script
by calling its name with a
$ prefix. So in the script whenever
$base, the value we defined for it above is used. If
you use advanced editors like GNU Emacs or even simpler ones like
Gedit (part of the GNOME graphical user interface) the variables will
become a different color which can really help in understanding the
script. We have put all the
$base variables in double quotation
") so the variable name and the following text do not
get mixed, the shell is going to ignore the
" after replacing
the variable value. To make the script executable, Sufi ran the
$ chmod +x mymock.sh
Then finally, Sufi ran the script, simply by calling its file name:
After the script finished, the only file remaining is the out.fits
file that Sufi had wanted in the beginning. Sufi then explained to the
student how he could run this script anywhere that he has a catalog if the
script is in the same directory. The only thing the student had to modify
in the script was the name of the catalog (the value of the
variable in the start of the script) and the value to the
variable if he changed the PSF size. The student was also happy to hear
that he won’t need to make it executable again when he makes changes later,
it will remain executable unless he explicitly changes the executable flag
The student was really excited, since now, through simple shell scripting, he could really speed up his work and run any command in any fashion he likes allowing him to be much more creative in his works. Until now he was using the graphical user interface which doesn’t have such a facility and doing repetitive things on it was really frustrating and some times he would make mistakes. So he left to go and try scripting on his own computer.
Sufi could now get back to his own work and see if the simulated nebula which resembled the one in the Andromeda constellation could be detected or not. Although it was extremely faint24, fortunately it passed his detection tests and he wrote it in the draft manuscript that would later become “Book of fixed stars”. He still had to check the other nebula he saw from Yemen and several other such objects, but they could wait until tomorrow (thanks to the shell script, he only has to define a new catalog). It was nearly sunset and they had to begin preparing for the night’s measurements on the ecliptic.
Abd al-rahman Sufi (903 – 986 A.D.), also known in Latin as Azophi was an Iranian astronomer. His manuscript “Book of fixed stars” contains the first recorded observations of the Andromeda galaxy, the Large Magellanic Cloud and seven other non-stellar or ‘nebulous’ objects.
The brightness of a diffuse object is added over all its pixels to give its final magnitude, see Flux Brightness and magnitude. So although the magnitude 3.44 (of the mock nebula) is orders of magnitude brighter than 6 (of the stars), the central galaxy is much fainter. Put another way, the brightness is distributed over a large area in the case of a nebula.