I have been working on a tool (ie: function) in MatLab to display spectral profile from FITS file we use to work with in astronomical spectroscopical community (ie: BeSS file format).
This is highly preliminary but just to start discussion around this subject, I publish here my initial code. Again, this is Work In Progress but maybe it can help you.
Just copy/paste this code into "otz_plot.m" file within matlab working directory.
Then go in matlab to a directory with at least one FITS file profile and type in the console for exemple:
otz_plot -h : for help
otz_plot 'filename.fits' : display your spectrum
otz_plot 'all' : display all FITS file spectra in your directory (could be messy if lot of them!)
otz_plot 'Ha' 'filename.fits' : to display Halpha from your spectrum (you can use 'Hb', 'Hg', 'D' for doublet, 'Ha+He' for both Halpha & HeI line...
otz_plot 6502 6603 0 4 'filename.fits' : here you specify the wavelength & Intensity limits
otz_plot 'filename.fits' -w 'Ha' : display in radial velocities Halpha
otz_plot 'filename.fits' -w 'Ha' -w 'Hb' -w 'Hg' : display in radial velocities Halpha, Hbeta & Hgamma
...
This is really WIP but do not hesitate to post here if you have comments or would like to see improvements in this code...
Code: Select all
function otz_plot(varargin)
%function otz_plot(filename)
% otz_plot.m
%
% Display and create a PDF of a graph of an echelle spectrum
%
% How to use:
% otz_plot [[L1 L2] Y1 Y2] filename1 -x param1 -x param2 param3 ...
% with L1 & L2 the wavelength (X axis) limits; if none, plot all spectrum
% with Y1 Y2 the Y-axis limits; if none, fit the graph
% use filename 'all' to use all .fits|.fit files in working directory
%
% v1.0 / 20160816 (c) Olivier Thizy - published in ARAS forum
% Developped with MatLab R2016a
%
% TODO LIST for future versions !!!
% ---------------------------------
% lot of ideas to come up! :-)
%
% PARAMETERS
%-----------
% clean up some parameters
clear x;
clear y;
clear filename;
clear wavelengths;
% Option: -h or -help
% ==>print help text
param_h = 0; % 0: doesn't print help
%
% Option: -f filaname1 -f filename2 -f filename3...
% ==>allow multiple spectra on same graph
NbFiles = 1; % always one filename, first one doesn't need -f tag...
%
% Option: -c r|b|rainbow
% ==>color of the graph.
% r, b...: red, blue; based on MatLab colors
% rainbow: one color for each spectrum
param_c = 'b'; % plot spectrum in red
%
% Option: -p pdf|png [X Y]
% ==>print PDF, PNG or none graph with X/Y size if provided (not
% implemented yet!)
param_p = 'none'; % print PDF file
%
% Option: -m linetype
% ==>mark set of lines marks on the graph
% Np for planetary nebulae
% Be for Be stars
% CV for Cataclysmic Variables
% O for O stars, B for B stars, A for A stars, F, G, K, M
% WN for Wolf-Rayet WN type
% WC for Wolf-Rayet WC type
param_m = 'none';
%
% Option: -t title
% ==>type of title displayed: short, long (default), object, none
param_t = 'short';
%
% Option: -e #
% ==>display echelle spectrum in multiple graphs (#: Nb of graphs)
% ==>if #<0, display the full spectrum on top line then the -# graphs
%
% Option: -s f|t
% ==>allow shift for each graphs either fixed (f) or time based (t)
%
% Option: -y X1 X2
% ==>rescale each graph using mean of intensity (Y axis) within (X1,X2: wavelength or velocities) mean
param_scale = 0;
%
% Option: -w wavelength
% ==>plot in Radial Velocity using lambda wavelength
% ==> if used multiple times, plot different lines on same graph
c = double(300000); % speed of light
param_w = 0;
DefaultRV = 500; % graph will be displayed by default within +/-DefaultRV limits
%
% Option: -z
% ==>correct from heliocentric correction (radial velocity)
param_z = 0;
%
% Get parameters input
nVarargs = length(varargin);
Param = '';
Xlimit1 = -inf;
Xlimit2 = inf;
Ylimit1 = -inf;
Ylimit2 = inf;
NbFiles = 1;
% List of known lines (TODO: accuracy to be improved)
KnownLines = {'Ha','6563.0','50';'Hb','4861.0','50';'Hg','4340.0','50';'Hd','4101.0','50';
'Ha+He','6610', '100';'H&K','3950','70';'HeI', '6678','50';'D','5888','38'};
% Get first arguments which do not require a command -X before
LastArg = nVarargs;
for j = nVarargs:-1:1
if strcmp(varargin{j}(1),'-')
LastArg = j-1;
end
end
switch LastArg
case 0
return;
case 1
tmp = varargin{1};
if strcmp(tmp,'-h')|strcmp(tmp,'-help') % Special for HELP
display('Tool to plot astronomical spectra in FITS & BeSS standard.');
display('(c) Olivier Thizy / thizy@free.fr');
display('Exemples:');
display('>otz_plot ''filename.fits''');
display('>otz_plot Ha ''filename.fits''');
display('(here you can use: Ha, Hb, Hg, Hd, Ha+He, He, D, HK)');
display('>otz_plot 6500 6600 ''filename.fits''');
display('>otz_plot 6500 6600 0 5 ''filename.fits''');
display('Sorry but extended HELP is not implemented yet...');
return;
else
filename{1} = varargin{1};
end
NextVarN = 1;
case 2
Param = varargin{1};
filename{1} = varargin{2};
NextVarN = 2;
case 3
if varargin{2}(1) == '-'
filename{1} = varargin{1};
NextVarN = 1;
else
Xlimit1 = str2num(varargin{1});
Xlimit2 = str2num(varargin{2});
filename{1} = varargin{3};
NextVarN = 3;
end
case 4
Param = varargin{1};
if varargin{3}(1) == '-'
filename{1} = varargin{2};
NextVarN = 2;
else
Ylimit1 = str2num(varargin{2});
Ylimit2 = str2num(varargin{3});
filename{1} = varargin{4};
NextVarN = 4;
end
case 5
Xlimit1 = str2num(varargin{1});
Xlimit2 = str2num(varargin{2});
Ylimit1 = str2num(varargin{3});
Ylimit2 = str2num(varargin{4});
filename{1} = varargin{5};
NextVarN = 5;
otherwise
Xlimit1 = str2num(varargin{1});
Xlimit2 = str2num(varargin{2});
Ylimit1 = str2num(varargin{3});
Ylimit2 = str2num(varargin{4});
filename{1} = varargin{5};
NextVarN = 6;
end
% get all FITS file from current directory if filename parameter is 'all'
if strcmp(filename{1},'all')
location = '.\';
ds = datastore(location,'Type','image','IncludeSubfolders',true,'FileExtensions',{'.fit','.fits','.FIT','.FITS'});
% if multiple directories, can use {location1,location2,location3} syntax
NbFiles = length(ds.Files);
for k = 1:NbFiles
filename{k} = char(ds.Files(k));
end
end
% if first filename is '?', then open a dialog box to get it
if filename{1}=='?'
[FileName, PathName] = uigetfile ('*.fits');
filename{1} = [PathName, FileName];
end
% Parse the -X arguments
for k = NextVarN:nVarargs
command=sscanf(varargin{k},'-%c');
switch command
case 'f' % multiple files plot
NbFiles = NbFiles + 1;
filename{NbFiles} = varargin{k+1};
k=k+1;
case 't' % title type
param_t = varargin{k+1};
k=k+1;
case 'c' % color for the graph(s)
param_c = varargin{k+1};
k=k+1;
case 'w' % Plot in velocity centered on wavelength(s)
param_w = param_w + 1;
if (k == nVarargs)
if strcmp(Param,'')
wavelengths{param_w} = (Xlimit1 + Xlimit2)/2;
else
for j = 1:size(KnownLines,1)
if strcmp(Param,KnownLines(j,1))
wavelengths{param_w} = str2double(KnownLines(j,2));
end
end
end
k=k+1;
else
if strcmp(varargin{k+1}(1),'-')
wavelengths{param_w} = (Xlimit1 + Xlimit2)/2;
for j = 1:size(KnownLines,1)
if strcmp(Param,KnownLines(j,1))
wavelengths{param_w} = str2double(KnownLines(j,2));
end
end
else
wavelengths{param_w} = str2double(varargin{k+1});
for j = 1:size(KnownLines,1)
if strcmp(varargin{k+1},KnownLines(j,1))
wavelengths{param_w} = str2double(KnownLines(j,2));
if Xlimit1 == -inf
Xlimit1 = double(-DefaultRV);
end
if Xlimit2 == inf
Xlimit2 = double(+DefaultRV);
end
end
end
end
k=k+1;
end
end
end
% check if the line center is given in text/alias form
for k = 1:size(KnownLines,1)
if strcmp(Param,KnownLines(k,1))
if param_w == 0
tmp1 = str2double(KnownLines(k,2));
tmp2 = str2double(KnownLines(k,3));
Xlimit1 = tmp1-tmp2;
Xlimit2 = tmp1+tmp2;
else
Xlimit1 = double(-DefaultRV);
Xlimit2 = double(+DefaultRV);
end
end
end
% Browse all files selected
for k = 1:NbFiles
% Extract FITS header and key infos from there
FITSHeader = fitsinfo(filename{k});
Data = fitsread(filename{k});
% Look for the size of the header (nb of keywords)
EnteteMax = max(size(FITSHeader.PrimaryData.Keywords));
% Extract some data from the header
% (to be improved, see rfitsinfo.m work in progress)
for l=1:EnteteMax
kwd = FITSHeader.PrimaryData.Keywords{l,1};
switch kwd
case 'NAXIS1'
NbPoints = int32(FITSHeader.PrimaryData.Keywords {l,2});
case 'CRVAL1'
Origine = FITSHeader.PrimaryData.Keywords {l,2};
case 'CDELT1'
Pas = FITSHeader.PrimaryData.Keywords {l,2};
case 'OBJNAME'
Objet = FITSHeader.PrimaryData.Keywords {l,2};
case 'DATE-OBS'
Date = FITSHeader.PrimaryData.Keywords {l,2};
case 'OBSERVER'
Observateur = FITSHeader.PrimaryData.Keywords {l,2};
case 'BSS-VHEL'
VHel = FITSHeader.PrimaryData.Keywords {l,2};
case 'EXPTIME'
ExpTimeTotal = FITSHeader.PrimaryData.Keywords {l,2};
case 'EXPTIME2'
ExpTime = FITSHeader.PrimaryData.Keywords {l,2};
case 'BSS_SITE'
SiteObs = FITSHeader.PrimaryData.Keywords {l,2};
case 'BSS_INST'
Instrument = FITSHeader.PrimaryData.Keywords {l,2};
case 'JD-OBS'
JDobs = FITSHeader.PrimaryData.Keywords {l,2};
case 'JD-MID'
JDmid = FITSHeader.PrimaryData.Keywords {l,2};
end
end
% Create spectrum data: wavelength, intensity
for a = 1 : NbPoints
Lambda = Origine + double(a-1) * Pas;
x (k,a) = double(Lambda);
y (k,a) = Data (1,a);
end
end
% display graph / open an half screen figure
figure('units','normalized','outerposition',[0.1 0.1 .5 .5])
% For each spectrum
for k = 1:NbFiles
if param_w == 0
plot(x(k,:), y(k,:), param_c);
hold on;
else
% For each central wavelength
for nw = 1:param_w
for j = 1:size(x,2)
w(k,j) = (x(k,j)-wavelengths{nw})*c/wavelengths{nw};
end
plot(w(k,:), y(k,:), param_c);
hold on;
end
end
end
% Define X & Y limits for the graph
x_limit = [Xlimit1 Xlimit2];
xlim(x_limit)
y_limit = [Ylimit1 Ylimit2];
ylim(y_limit)
% Display title above the first graph with last file data
switch param_t
case 'long'
Titre2 = [Objet, ' (', Date, ' / ', ExpTime, ') @ ', SiteObs, ' w/ ', Instrument,'; (c) ', Observateur];
case 'short'
Titre2 = [Objet, ' - ', Observateur];
case 'object'
Titre2 = Objet;
case 'none'
Titre2 = '';
end
if strcmp(Titre2,'')
else
title(Titre2, 'Interpreter','none');
end
if param_w == 0
xlabel('Wavelenght in Â');
else
xlabel('Velocity in km/s');
end
ylabel('Relative flux');
% save graph in PDF & PNG using 1st filename
[pathstr,name,ext] = fileparts(filename{1});
orient landscape;
outputfile = ['graph' name];
switch param_p
case 'pdf'
print (outputfile, '-painters', '-dpdf', '-bestfit');
case 'png'
orient portrait;
print (outputfile, '-dpng');
end
% That's all folks !