1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
program astap_command_line;
{Copyright (C) 2017, 2024 by Han Kleijn, www.hnsky.org
email: han.k.. at...hnsky.org
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/. }
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX or ANDROID}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils, CustApp,
unit_command_line_solving, unit_command_line_general;
type
{Tastap}
Tastap = class(TCustomApplication)
protected
procedure DoRun; override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
end;
{Tastap}
function fits_file_name(inp : string): boolean; {fits file name?}
begin
inp:=uppercase(extractfileext(inp));
result:=((inp='.FIT') or (inp='.FITS') or (inp='.FTS'));
end;
procedure Tastap.DoRun;
var
file_loaded,filespecified,analysespecified, extractspecified, extractspecified2 : boolean;
backgr, hfd_median,snr_min : double;
hfd_counter,report : integer;
begin
{$IfDef Darwin}// for OS X,
database_path:='/usr/local/opt/astap/';
{$else}
database_path:=extractfilepath(paramstr(0));{}
{$ifdef mswindows}
{$else} {UNIX or ANDROID}
if copy(database_path,1,4)='/usr' then {for Linux distributions}
database_path:='/usr/share/astap/data/';
{$endif}
{$endif}
fov_specified:=false;{assume no FOV specification in commandline}
if ((paramcount=0) or (hasOption('h','help'))) then
begin
writeln(
'ASTAP astrometric solver version CLI-'+astap_version+#10+
'(C) 2018, 2024 by Han Kleijn. License MPL 2.0, Webpage: www.hnsky.org'+#10+
'Usage:'+#10+
'-f filename {fits, tiff, png, jpg files}'+#10+
'-r radius_area_to_search[degrees]'+#10+ {changed}
'-fov diameter_field[degrees] {enter zero for auto}'+#10+ {changed}
'-ra center_right_ascension[hours]'+#10+
'-spd center_south_pole_distance[degrees]'+#10+
'-s max_number_of_stars {default 500}'+#10+
'-t tolerance {default 0.007}'+#10+
'-m minimum_star_size["] {default 1.5}'+#10+
'-z downsample_factor[0,1,2,3,4] {Downsample prior to solving. 0 is auto}'+#10+
'-check apply[y/n] {Apply check pattern filter prior to solving. Use for raw OSC images only when binning is 1x1}' +#10+
'-d path {specify a path to the star database}'+#10+
'-D abbreviation {Specify a star database [d80,d50,..]}'+#10+
'-o file {Name the output files with this base path & file name}'+#10+
'-sip {Add SIP (Simple Image Polynomial) coefficients}'+#10+
'-speed mode[auto/slow] {Slow is forcing reading a larger area from the star database (more overlap) to improve detection}'+#10+
'-wcs {Write a .wcs file in similar format as Astrometry.net. Else text style.}' +#10+
'-log {Write the solver log to file}'+#10+
'-update {update the FITS header with the found solution. Jpeg, png, tiff will be written as fits}' +#10+
'-progress {Log all progress steps and messages}'+#10+
#10+
'Analyse options:' +#10+
'-analyse snr_min {Analyse only and report median HFD and number of stars used}'+#10+
'-extract snr_min {As -analyse but additionally export info of all detectable stars to a .csv file}'+#10+
'-extract2 snr_min {Solve and export info of all detectable stars to a .csv file including ra, dec.}'+#10+
'Preference will be given to the command line values.'
);
esc_pressed:=true;{kill any running activity. This for APT}
terminate;
exit;
end;
filespecified:=hasoption('f');
if filespecified then
begin
commandline_log:=hasoption('log');{log to file. In debug mode enable logging to memo2}
solve_show_log:=hasoption('progress');{log all progress}
if commandline_log then memo2_message(cmdline);{write the original commmand line}
if filespecified then
begin
filename2:=GetOptionValue('f');
file_loaded:=load_image; {load file first to give commandline parameters later priority}
if file_loaded=false then errorlevel:=16;{error file loading}
end
else
file_loaded:=false;
{apply now overriding parameters}
if hasoption('fov') then
begin
fov_specified:=true; {do not calculate it from header};
search_fov1:=GetOptionValue('fov');
end;
if hasoption('r') then radius_search1:=GetOptionValue('r');
if hasoption('ra') then
begin
ra0:=strtofloat2(GetOptionValue('ra'))*pi/12;
end;
{else ra from fits header}
if hasoption('spd') then {south pole distance. Negative values can't be passed via commandline}
begin
dec0:=(strtofloat2(GetOptionValue('spd'))-90)*pi/180;{convert south pole distance to declination}
end;
{else dec from fits header}
if hasoption('z') then downsample_for_solving1:=strtoint(GetOptionValue('z'));
if hasoption('s') then max_stars:=strtoint(GetOptionValue('s'));
if hasoption('t') then quad_tolerance1:=GetOptionValue('t');
if hasoption('m') then min_star_size1:=GetOptionValue('m');
if hasoption('sip') then add_sip1:='n'<>GetOptionValue('sip');
if hasoption('speed') then force_oversize1:=pos('slow',GetOptionValue('speed'))<>0;
if hasoption('check') then check_pattern_filter1:=('y'=GetOptionValue('check'));
extractspecified:=hasoption('extract');
extractspecified2:=hasoption('extract2');
if extractspecified2 then add_sip1:=true;//force sip for high accuracy
analysespecified:=hasoption('analyse');
if ((file_loaded) and ((analysespecified) or (extractspecified)) ) then {analyse fits and report HFD value in errorlevel }
begin
if analysespecified then
begin
snr_min:=strtofloat2(getoptionvalue('analyse'));
report:=0; {report nr stars and hfd only}
end;
if extractspecified then
begin
snr_min:=strtofloat2(getoptionvalue('extract'));
report:=2; {report nr stars and hfd and export csv file}
end;
if snr_min=0 then snr_min:=30;
analyse_image(img_loaded,snr_min,report, hfd_counter,backgr,hfd_median); {find background, number of stars, median HFD}
if isConsole then {stdout available, compile targe option -wh used}
begin
writeln('HFD_MEDIAN='+floattostrF2(hfd_median,0,1));
writeln('STARS='+inttostr(hfd_counter));
end;
{$IFDEF msWindows}
halt(round(hfd_median*100)*1000000+hfd_counter);{report in errorlevel the hfd and the number of stars used}
{$ELSE}
halt(errorlevel);{report hfd in errorlevel. In linux only range 0..255 possible}
{$ENDIF}
end;{analyse fits and report HFD value}
if hasoption('d') then
database_path:=GetOptionValue('d')+DirectorySeparator; {specify a different database path}
if hasoption('D') then
star_database1:=GetOptionValue('D'); {specify a different database}
if ((file_loaded) and (solve_image(img_loaded ))) then {find plate solution, filename2 extension will change to .fit}
begin
if hasoption('o') then filename2:=GetOptionValue('o');{change file name for .ini file}
write_ini(true);{write solution to ini file}
add_long_comment('cmdline:'+cmdline);{log command line in wcs file}
if hasoption('update') then
begin
if fits_file_name(filename2) then SaveFITSwithupdatedheader1
else
save_fits16bit(img_loaded,ChangeFileExt(filename2,'.fits'));{save original png,tiff jpg to 16 bits fits file}
end;
remove_key('NAXIS1 =',true{one});
remove_key('NAXIS2 =',true{one});
update_integer('NAXIS =',' / Minimal header ' ,0);{2 for mono, 3 for colour}
update_integer('BITPIX =',' / ' ,8);
if hasoption('wcs') then
write_astronomy_wcs {write WCS astronomy.net style}
else
try Memo1.SavetoFile(ChangeFileExt(filename2,'.wcs'));{save header as wcs file} except {sometimes error using APT, locked?} end;
end {solution}
else
begin {no solution}
if hasoption('o') then filename2:=GetOptionValue('o'); {change file name for .ini file}
write_ini(false);{write solution to ini file}
errorlevel:=1;{no solution}
end;
if ((file_loaded) and (extractspecified2)) then
begin
snr_min:=strtofloat2(getoptionvalue('extract2'));
if snr_min=0 then snr_min:=30;
analyse_image(img_loaded,snr_min,2 {report, export CSV only}, hfd_counter,backgr,hfd_median); {find background, number of stars, median HFD}
end;
esc_pressed:=true;{kill any running activity. This for APT}
if commandline_log then
Memo2.SavetoFile(ChangeFileExt(filename2,'.log'));{save Memo2 log to log file}
halt(errorlevel);
// Exit status:
// 0 no errors.
// 1 no solution.
// 2 not enough stars detected.
// 16 error reading image file.
// 32 no star database found.
// 33 error reading star database.
// ini file is always written. Could contain:
// ERROR=......
// WARNING=......
// wcs file is written when there is a solution. Could contain:
// WARNING =.........
end;{-f option}
{$IfDef Darwin}// for OS X,
{$IF FPC_FULLVERSION <= 30200} {FPC3.2.0}
application.messagebox( pchar('Warning this code requires later LAZARUS 2.1 and FPC 3.3.1 version!!!'), pchar('Warning'),MB_OK);
{$ENDIF}
{$ENDIF}
terminate;
end;
constructor Tastap.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
memo1:=Tstringlist.Create;
memo2:=Tstringlist.Create;
StopOnException:=True;
end;
destructor Tastap.Destroy;
begin
memo2.free;
memo1.free;
inherited Destroy;
end;
var
Application: Tastap;
//{$R *.res}
{$R *.res}
begin
Application:=Tastap.Create(nil);
Application.Run;
Application.Free;
end.
|