File: unit_monitoring.pas

package info (click to toggle)
astap 2024.11.13-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,032 kB
  • sloc: pascal: 49,240; sh: 205; makefile: 5
file content (301 lines) | stat: -rw-r--r-- 11,017 bytes parent folder | download
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
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
unit unit_monitoring;
{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 delphi}

interface

uses
  Classes, SysUtils,forms,fileutil,
  graphics, LCLIntf,math;


procedure monitoring(path :string);{stack live average}
procedure report_delta; {report delta error}

var
  live_monitoring: boolean=false; {used to inhibit solving while live_stacking}

implementation

uses unit_stack, astap_main,unit_stack_routines,unit_astrometric_solving,unit_star_align,unit_inspector_plot, unit_hjd;

var
  latest_time : integer=0;

function file_available(monitor_directory:string; out filen: string ) : boolean; {check if fits file is available and report the filename}
Var
  Info : TSearchRec;
  Count : Longint;
  i     : integer;
  f     : file;
Begin
  result:=false;
  Count:=0;
  If SysUtils.FindFirst (monitor_directory+ {$ifdef mswindows}'\' {$else} {unix} '/' {$endif}+'*', faAnyFile-faDirectory,Info)=0 then
  begin
    Repeat
      Inc(Count);
      With Info do
      begin
      //  SR.FindData.ftLastWriteTime
        if ((time>latest_time) and (image_file_name(name){readable image name?} )) then
        begin
          result:=true;
          filen:=name;
          latest_time:=time;
        end;
      end;
    Until SysUtils.FindNext(info)<>0;
    SysUtils.FindClose(Info);
  end;

  if result then
  begin
    filen:= monitor_directory+ {$ifdef mswindows}'\' {$else} {unix} '/' {$endif}+filen;
    {check if free for reading}
    assign(f,filen);
    {$I-}
    reset(f); {prepare for reading}
    {$I+}
    result:=(IOresult=0); {report if file is accessible}
    if result then
      close(f);
  end;
end;


procedure report_delta; {report delta error}
var
  distance,deltaRA,deltaDEC,az_solution,alt_solution,az_target,alt_target,jd_now,lat,long,angle,angle1,angle2,angle_mid,fov : double;
  wdiv2,hdiv2,x,y,rx,ry : integer;
  direction : string;
begin
  if ((head.naxis=0) or (head.cd1_1=0)) then exit;
  with stackmenu1 do
  begin
    raposition1.visible:=true;
    decposition1.visible:=true;
    raposition1.caption:='  '+prepare_ra(head.ra0,': ');{show center of image}
    decposition1.caption:=prepare_dec(head.dec0,'° ');

    if copy(target1.caption,1,1)<>'-' then {target option and object is set}
    begin
      target_distance1.visible:=true;
      delta_ra1.visible:=true;
      delta_dec1.visible:=true;
      label_latitude1.Visible:=true;
      label_longitude1.Visible:=true;
      monitor_latitude1.visible:=true;
      monitor_longitude1.visible:=true;

      ang_sep(head.ra0,head.dec0,ra_target,dec_target ,distance);{calculate distance in radians}
      target_distance1.caption :='Distance: '+floattostrF(distance*180/pi,ffFixed,0,3)+'°';

      deltaRA:=fnmodulo((ra_target-head.ra0)*12/pi,24);
      if deltaRA>12 then begin direction:='W'; deltaRa:=24-deltaRA;end else begin direction:='E'; end;
      delta_ra1.caption :='Δα:  '+floattostrF(deltaRA,ffFixed,0,3)+'h '+direction;

      deltaDec:=(dec_target-head.dec0)*180/pi;
      if deltaDec>0 then begin direction:='N' end else begin direction:='S'; end;
      delta_dec1.caption:='Δδ:  '+floattostrF(abs(deltaDec),ffFixed,0,3)+'° '+direction;


      jd_now:=calc_jd_now;
      lat:=strtofloat2(lat_default)*pi/180;
      long:=strtofloat2(long_default)*pi/180;
      altitude_and_refraction(lat,long,jd_now,10 {temp},1010 {pressure},head.ra0,head.dec0,az_solution,alt_solution);{In formulas the longitude is positive to west!!!. }
      altitude_and_refraction(lat,long,jd_now,10 {temp},1010 {pressure},ra_target,dec_target,az_target,alt_target);{In formulas the longitude is positive to west!!!. }

      target_altitude1.visible:=true;
      target_azimuth1.visible:=true;
      target_altitude1.caption:='A:  '+floattostrF(alt_target,ffFixed,0,1)+'°';
      target_azimuth1.caption:='H:  '+floattostrF(az_target,ffFixed,0,1)+'°';


      {draw arrow}
      with stackmenu1.direction_arrow1 do
      begin
        canvas.brush.color:=clmenu;
        Canvas.FillRect(rect(0,0,width,height));
        mainwindow.image1.Canvas.Pen.mode:=pmXor;
        Canvas.Pen.Color := clred;
        canvas.pen.Width:=5;
        Canvas.brush.Style:=bsClear;
        wdiv2:=width div 2;
        hdiv2:=height div 2;

        if ((lat=0) and (long=0)) then
        begin
          canvas.font.size:=14;
          canvas.textout(10,hdiv2+30,'Set latitude and longitude!!');
        end;

        //show where the image sensor is
        Canvas.brush.Style:=bsDiagCross;
        canvas.brush.color:=clred;
        fov:=head.height*head.cdelt2;
        rx:=round(wdiv2+wdiv2*(az_target-az_solution)/fov);
        ry:=round(hdiv2-hdiv2*(alt_target-alt_solution)/fov);
        rectangle(canvas.handle,rx-wdiv2+10,ry-hdiv2+10,rx+wdiv2-10,ry+hdiv2-10);


        //arrow
        Canvas.brush.Style:=bsclear;
        fov:=head.height*head.cdelt2;
        rx:=round(wdiv2+wdiv2*(az_target-az_solution)/fov);
        ry:=round(hdiv2-hdiv2*(alt_target-alt_solution)/fov);
        rectangle(canvas.handle,rx-wdiv2+10,ry-hdiv2+10,rx+wdiv2-10,ry+hdiv2-10);

        ellipse(canvas.handle,wdiv2-8,hdiv2-8,wdiv2+8+1,hdiv2+8+1);
        moveToex(Canvas.handle,wdiv2,hdiv2,nil);

        angle:=arctan2(alt_target-alt_solution, az_target-az_solution);//calculate direction to target
        x:=round(0.95*wdiv2*cos(angle));
        y:=round(0.95*wdiv2*sin(angle));
        lineTo(Canvas.handle,hdiv2+x,wdiv2-y); // arrow line. Note y counts from top to bottom, so minus sign

        angle1:=angle+(180+20)*pi/180;
        angle_mid:=angle+90*pi/180;
        angle2:=angle-20*pi/180;

        x:=x+round(30*cos(angle1));
        y:=y+round(30*sin(angle1));
        lineTo(Canvas.handle,hdiv2+x,wdiv2-y); // arrowhead. Note y counts from top to bottom, so minus sign.
        x:=x+round(21*cos(angle_mid));
        y:=y+round(21*sin(angle_mid));
        lineTo(Canvas.handle,hdiv2+x,wdiv2-y); // arrowhead. Note y counts from top to bottom, so minus sign
        x:=x+round(30*cos(angle2));
        y:=y+round(30*sin(angle2));
        lineTo(Canvas.handle,hdiv2+x,wdiv2-y); // arrowhead. Note y counts from top to bottom, so minus sign

      end;
    end;//target specified
  end;
end;


procedure monitoring(path :string);{monitoring a directory}
var
  counter       : integer;
  count         : integer=0;
  solver        :  boolean;
begin
  with stackmenu1 do
  begin

    esc_pressed:=false;

    if monitor_applydarkflat1.checked then   {Prepare for dark and flats}
    begin
      analyse_listview(stackmenu1.listview2,false {light},false {full fits},false{refresh});{analyse dark tab, by loading=false the loaded img will not be effected. Calstat will not be effected}
      analyse_listview(stackmenu1.listview3,false {light},false {full fits},false{refresh});{analyse flat tab, by loading=false the loaded img will not be effected}
    end;

    {live stacking}
    repeat
    begin
      if file_available(path,filename2 {file found}) then
      begin
        try { Do some lengthy operation }
          Application.ProcessMessages;
          {load image}
          if ((esc_pressed) or (load_image(filename2,img_loaded,head,mainwindow.memo1.lines,false,false {plot})=false)) then
          begin

            if esc_pressed=false then
            begin
              memo2_message('Error loading file'); {can't load}
              continue; {repeat loop}
            end;
            live_monitoring1.font.style:=[];
            live_monitoring:=false;
            exit;
          end;
          memo2_message('Loading file: '+filename2) ;

          if monitor_applydarkflat1.checked then
          begin
            apply_dark_and_flat(img_loaded,head);{apply dark, flat if required, renew if different head.exposure or ccd temp}
            {these global variables are passed-on in procedure to protect against overwriting}
            update_text(mainwindow.memo1.lines,'CALSTAT =',#39+head.calstat+#39);
            if ((pos('D',head.calstat)>0) or (pos('F',head.calstat)>0))  then {status of dark application}
              memo2_message('Calibration status '+head.calstat+'. Used '+inttostr(head.dark_count)+' darks, '+inttostr(head.flat_count)+' flats, '+inttostr(head.flatdark_count)+' flat-darks') ;
          end;


          Application.ProcessMessages;
          if esc_pressed then exit;

          if ((head.naxis3=1) and (mainwindow.preview_demosaic1.checked)) then
             demosaic_advanced(img_loaded) {demosaic and set levels}
          else
            use_histogram(img_loaded,true {update}); {plot histogram, set sliders}

          plot_fits(mainwindow.image1,false,true{do not show header in memo1});{plot real}

          monitor_date1.caption:= DateTimeToStr(FileDateToDateTime(latest_time));

          solver:=false;
          case stackmenu1.monitor_action1.itemindex of 1: CCDinspector(30,true {screenplot},false,strtofloat(measuring_angle));
                                                       2: CCDinspector(30,true {screenplot},true,strtofloat(measuring_angle));
                                                       3: form_inspection1.aberration_inspector1Click(nil);
                                                       4: solver:=true;
                                                       5: form_inspection1.background_contour1Click(nil);
          end;{case}
          if solver then
          begin
            mainwindow.astrometric_solve_image1Click(nil);
            report_delta;
          end
          else
          begin
            target_distance1.visible:=false;
            raposition1.visible:=false;
            decposition1.visible:=false;
            delta_ra1.visible:=false;
            delta_dec1.visible:=false;
            label_latitude1.Visible:=false;
            label_longitude1.Visible:=false;
            monitor_latitude1.visible:=false;
            monitor_longitude1.visible:=false;
          end;


        finally
        end;
      end
      else
      begin
        wait(1000);{wait 1 second unless something happens}
        if count=0 then live_monitoring1.caption:='  ▶'
        else
        if count=1 then live_monitoring1.caption:='▶  '
        else
        if count=2 then live_monitoring1.caption:=' ▶ ';

        inc(count);
        if count>2 then count:=0;

      end;

    end;{live average}

    until esc_pressed;

    live_monitoring:=false;
    live_monitoring1.font.style:=[];
    memo2_message('Monitoring stopped.');

    counterL:=counter;
  end;{with stackmenu1}
end;


end.