1 |
/** |
2 |
@defgroup rebin2 rebin2 reduce/increase resolution to that of MDI/HMI |
3 |
@ingroup su_util |
4 |
|
5 |
@brief Reduce (increase) the resolution of the input data to that of MDI (HMI) by factor of 2. |
6 |
|
7 |
@par Synopsis: |
8 |
@code |
9 |
rebin2 in=input data out=output data factor=2*n mode=simple |
10 |
where n is a multiple/fraction of 2. |
11 |
@endcode |
12 |
|
13 |
This is a general purpose module that takes a series of input |
14 |
data and modifies its spatial resolution by a factor (multiples |
15 |
or fractions of 2) as required and gives out a set of output |
16 |
data. The method for avaraging (interpolation) can be specified |
17 |
through the input "mode". The current version handles a simple |
18 |
boxcar average. If 'scale' < 0 then the input is reduced in size to 1/|scale|. |
19 |
|
20 |
Make sure you created the appropriate output series before running |
21 |
the program. For example, su_bala.rebin2up.jsd |
22 |
|
23 |
@par Flags: |
24 |
@c none |
25 |
Currently it doesn't have any flags. |
26 |
|
27 |
@par GEN_FLAGS: |
28 |
Ubiquitous flags present in every module. |
29 |
@ref jsoc_main |
30 |
|
31 |
@param in The input data series. |
32 |
@param out The output series. |
33 |
|
34 |
@par Exit_Status: |
35 |
Brief description of abnormal, non-zero, exit values. |
36 |
|
37 |
@par Example: |
38 |
Takes a series of 1024 X 1024 MDI full disk magnetogram and |
39 |
produces images with the resolution of HMI, 4096 X 4096. |
40 |
|
41 |
@code |
42 |
rebin2 in='mdi.fd_M_96m_lev18[2003.10.20/1d]' out='su_bala.rebin2up' scale=4 mode='simple' |
43 |
@endcode |
44 |
|
45 |
@par Example: |
46 |
Reduces the resolution of HMI images 4096 X 4096 to that of MDI, |
47 |
1024 X 1024. Here the input is the HMI images and the output |
48 |
is the lower resolution HMI images. |
49 |
@code |
50 |
rebin2 in='su_bala.rebin2up[2003.10.20/1d]' out='su_bala.rebin2down' scale=0.25 mode='simple' |
51 |
@endcode |
52 |
|
53 |
@bug |
54 |
None known so far. |
55 |
|
56 |
@par Code: |
57 |
The doxygen code that makes this page is here: |
58 |
@verbinclude ./doxygen_moduletemplate.txt |
59 |
*/ |
60 |
|
61 |
#include "jsoc.h" |
62 |
#include "jsoc_main.h" |
63 |
#include "fstats.h" |
64 |
|
65 |
char *module_name = "rebin2"; |
66 |
|
67 |
#define DIE(msg) {fflush(stdout);fprintf(stderr,"%s, status=%d\n",msg,status); return(status);} |
68 |
|
69 |
ModuleArgs_t module_args[] = |
70 |
{ |
71 |
{ARG_STRING, "in", "NOT SPECIFIED", "Input data series."}, |
72 |
{ARG_STRING, "out", "NOT SPECIFIED", "Output data series."}, |
73 |
{ARG_FLOAT, "scale", "NOTSPECIFIED", "Scale factor. negative for shrink factor"}, |
74 |
{ARG_STRING, "mode", "simple", "conversion type."}, |
75 |
{ARG_END} |
76 |
}; |
77 |
|
78 |
int DoIt(void) |
79 |
{ |
80 |
int status = DRMS_SUCCESS; |
81 |
DRMS_RecordSet_t *inRS, *outRS; |
82 |
int irec, nrecs; |
83 |
const char *inQuery = params_get_str(&cmdparams, "in"); |
84 |
const char *outSeries = params_get_str(&cmdparams, "out"); |
85 |
const char *mode = params_get_str(&cmdparams, "mode"); |
86 |
int scale = params_get_int(&cmdparams, "scale"); |
87 |
int iscale, factor; |
88 |
float fscale; |
89 |
if (scale < 0.0) |
90 |
{ // shrinking |
91 |
iscale = -scale; |
92 |
fscale = 1.0/iscale; |
93 |
} |
94 |
else |
95 |
{ // enlarging |
96 |
iscale = (int) scale; |
97 |
fscale = scale; |
98 |
} |
99 |
|
100 |
inRS = drms_open_records(drms_env, inQuery, &status); |
101 |
if (status || inRS->n == 0) |
102 |
DIE("No input data found"); |
103 |
nrecs = inRS->n; |
104 |
if (nrecs == 0) |
105 |
DIE("No records found"); |
106 |
outRS = drms_create_records(drms_env, nrecs, (char *)outSeries, DRMS_PERMANENT, &status); |
107 |
if (status) |
108 |
DIE("Output recordset not created"); |
109 |
|
110 |
for (irec=0; irec<nrecs; irec++) |
111 |
{ |
112 |
DRMS_Record_t *outRec, *inRec; |
113 |
DRMS_Segment_t *outSeg, *inSeg; |
114 |
DRMS_Array_t *inArray, *outArray; |
115 |
float *inData, *outData; |
116 |
int inx, iny, outx, outy, i, j; |
117 |
float val; |
118 |
int quality=0; |
119 |
|
120 |
inRec = inRS->records[irec]; |
121 |
quality = drms_getkey_int(inRec, "QUALITY", &status); |
122 |
if (status || (!status && quality >= 0)) |
123 |
{ |
124 |
inSeg = drms_segment_lookupnum(inRec, 0); |
125 |
inArray = drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status); |
126 |
if (status) |
127 |
{ |
128 |
printf(" No data file found but QUALITY not bad, status=%d\n", status); |
129 |
drms_free_array(inArray); |
130 |
continue; |
131 |
} |
132 |
|
133 |
int naxis = inArray->naxis; |
134 |
int in_nx = inArray->axis[0]; |
135 |
int in_ny = inArray->axis[1]; |
136 |
int in_inc = (scale < 0 ? 1 : iscale); |
137 |
int out_inc = (scale < 0 ? iscale : 1); |
138 |
int out_nx = in_nx * fscale; |
139 |
int out_ny = in_ny * fscale; |
140 |
|
141 |
int outDims[2] = {out_nx, out_ny}; |
142 |
inData = (float *)inArray->data; |
143 |
outArray = drms_array_create(DRMS_TYPE_FLOAT, naxis, outDims, NULL, &status); |
144 |
outData = (float *)outArray->data; |
145 |
|
146 |
if (strcmp(mode, "simple")==0) // setup for better HMI proxy |
147 |
{ |
148 |
if (scale < 0) // need to average input chunk |
149 |
{ |
150 |
for (outy = 0; outy < out_ny; outy += 1) |
151 |
for (outx = 0; outx < out_nx; outx += 1) |
152 |
{ |
153 |
double total = 0.0; |
154 |
int nn = 0; |
155 |
for (j = 0; j < in_inc; j += 1) |
156 |
for (i = 0; i < in_inc; i += 1) |
157 |
{ |
158 |
val = inData[in_nx*(outy*iscale + j) + outx*iscale + i]; |
159 |
if (!drms_ismissing_float(val)) |
160 |
{ |
161 |
total = total + val; |
162 |
nn++; |
163 |
} |
164 |
} |
165 |
outData[out_nx*outy + outx] = (nn > 0 ? total/nn : DRMS_MISSING_FLOAT); |
166 |
} |
167 |
} |
168 |
else // need to replicate input point |
169 |
{ |
170 |
for (iny = 0; iny < in_ny; iny += 1) |
171 |
for (inx = 0; inx < in_nx; inx += 1) |
172 |
{ |
173 |
val = inData[in_nx*iny + inx]; |
174 |
for (j = 0; j < out_inc; j += 1) |
175 |
for (i = 0; i < out_inc; i += 1) |
176 |
outData[out_nx*(iny*iscale + j) + inx*iscale + i] = val; |
177 |
} |
178 |
} |
179 |
} |
180 |
else |
181 |
DIE("invalid conversion mode"); |
182 |
|
183 |
drms_free_array(inArray); |
184 |
|
185 |
// write data file |
186 |
outRec = outRS->records[irec]; |
187 |
outSeg = drms_segment_lookupnum(outRec, 0); |
188 |
|
189 |
// copy all keywords |
190 |
drms_copykeys(outRec, inRec, 0, kDRMS_KeyClass_Explicit); |
191 |
set_statistics(outSeg, outArray, 1); |
192 |
|
193 |
// Now fixup coordinate keywords |
194 |
// Only CRPIX1,2 and CDELT1,2 should need repair. |
195 |
drms_setkey_double(outRec, "CDELT1", drms_getkey_double(inRec, "CDELT1", NULL)/fscale); |
196 |
drms_setkey_double(outRec, "CDELT2", drms_getkey_double(inRec, "CDELT2", NULL)/fscale); |
197 |
drms_setkey_double(outRec, "CRPIX1", (drms_getkey_double(inRec, "CRPIX1", NULL)-0.5) * fscale + 0.5); |
198 |
drms_setkey_double(outRec, "CRPIX2", (drms_getkey_double(inRec, "CRPIX2", NULL)-0.5) * fscale + 0.5); |
199 |
drms_setkey_int(outRec, "SCALE", scale); |
200 |
|
201 |
|
202 |
// get info for array from segment |
203 |
outArray->bzero = outSeg->bzero; |
204 |
outArray->bscale = outSeg->bscale; |
205 |
outArray->parent_segment = outSeg; |
206 |
|
207 |
status = drms_segment_write(outSeg, outArray, 0); |
208 |
if (status) |
209 |
DIE("problem writing file"); |
210 |
drms_free_array(outArray); |
211 |
} |
212 |
} //end of "irec" loop |
213 |
|
214 |
drms_close_records(inRS, DRMS_FREE_RECORD); |
215 |
drms_close_records(outRS, DRMS_INSERT_RECORD); |
216 |
return (DRMS_SUCCESS); |
217 |
} // end of DoIt |