(file) Return to sw_functions.c CVS log (file) (dir) Up to [Development] / JSOC / proj / sharp / apps

   1 mbobra 1.37 
   2 xudong 1.1  /*===========================================
   3 xudong 1.27  
   4 mbobra 1.40  The following functions calculate these spaceweather indices from the vector magnetic field data:
   5 xudong 1.27  
   6              USFLUX Total unsigned flux in Maxwells
   7              MEANGAM Mean inclination angle, gamma, in degrees
   8              MEANGBT Mean value of the total field gradient, in Gauss/Mm
   9              MEANGBZ Mean value of the vertical field gradient, in Gauss/Mm
  10              MEANGBH Mean value of the horizontal field gradient, in Gauss/Mm
  11              MEANJZD Mean vertical current density, in mA/m2
  12              TOTUSJZ Total unsigned vertical current, in Amperes
  13              MEANALP Mean twist parameter, alpha, in 1/Mm
  14              MEANJZH Mean current helicity in G2/m
  15              TOTUSJH Total unsigned current helicity in G2/m
  16              ABSNJZH Absolute value of the net current helicity in G2/m
  17              SAVNCPP Sum of the Absolute Value of the Net Currents Per Polarity in Amperes
  18              MEANPOT Mean photospheric excess magnetic energy density in ergs per cubic centimeter
  19              TOTPOT Total photospheric magnetic energy density in ergs per cubic centimeter
  20              MEANSHR Mean shear angle (measured using Btotal) in degrees
  21 mbobra 1.40  CMASK The total number of pixels that contributed to the calculation of all the indices listed above
  22             
  23              And these spaceweather indices from the line-of-sight magnetic field data:
  24              USFLUXL Total unsigned flux in Maxwells
  25              MEANGBL Mean value of the line-of-sight field gradient, in Gauss/Mm
  26              CMASKL The total number of pixels that contributed to the calculation of USFLUXL and MEANGBL
  27 mbobra 1.29  R_VALUE Karel Schrijver's R parameter
  28 xudong 1.27  
  29              The indices are calculated on the pixels in which the conf_disambig segment is greater than 70 and
  30              pixels in which the bitmap segment is greater than 30. These ranges are selected because the CCD
  31              coordinate bitmaps are interpolated for certain data (at the time of this CVS submit, all data
  32              prior to 2013.08.21_17:24:00_TAI contain interpolated bitmaps; data post-2013.08.21_17:24:00_TAI
  33              contain nearest-neighbor bitmaps).
  34              
  35              In the CCD coordinates, this means that we are selecting the pixels that equal 90 in conf_disambig
  36              and the pixels that equal 33 or 34 in bitmap. Here are the definitions of the pixel values:
  37              
  38              For conf_disambig:
  39              50 : not all solutions agree (weak field method applied)
  40              60 : not all solutions agree (weak field + annealed)
  41              90 : all solutions agree (strong field + annealed)
  42              0 : not disambiguated
  43              
  44              For bitmap:
  45              1  : weak field outside smooth bounding curve
  46              2  : strong field outside smooth bounding curve
  47              33 : weak field inside smooth bounding curve
  48              34 : strong field inside smooth bounding curve
  49 xudong 1.27  
  50              Written by Monica Bobra 15 August 2012
  51              Potential Field code (appended) written by Keiji Hayashi
  52              Error analysis modification 21 October 2013
  53              
  54              ===========================================*/
  55 xudong 1.1  #include <math.h>
  56 mbobra 1.9  #include <mkl.h>
  57 xudong 1.1  
  58 mbobra 1.9  #define PI       (M_PI)
  59 xudong 1.1  #define MUNAUGHT (0.0000012566370614) /* magnetic constant */
  60             
  61             /*===========================================*/
  62             
  63             /* Example function 1: Compute total unsigned flux in units of G/cm^2 */
  64             
  65 xudong 1.27 //  To compute the unsigned flux, we simply calculate
  66 xudong 1.1  //  flux = surface integral [(vector Bz) dot (normal vector)],
  67             //       = surface integral [(magnitude Bz)*(magnitude normal)*(cos theta)].
  68             //  However, since the field is radial, we will assume cos theta = 1.
  69             //  Therefore the pixels only need to be corrected for the projection.
  70             
  71             //  To convert G to G*cm^2, simply multiply by the number of square centimeters per pixel.
  72             //  As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
  73             //  (Gauss/pix^2)(CDELT1)^2(RSUN_REF/RSUN_OBS)^2(100.cm/m)^2
  74 mbobra 1.20 //  =Gauss*cm^2
  75 xudong 1.1  
  76 xudong 1.27 int computeAbsFlux(float *bz_err, float *bz, int *dims, float *absFlux,
  77                                float *mean_vf_ptr, float *mean_vf_err_ptr, float *count_mask_ptr, int *mask,
  78 mbobra 1.9                     int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
  79 xudong 1.1  
  80             {
  81 xudong 1.27     
  82 mbobra 1.14     int nx = dims[0];
  83                 int ny = dims[1];
  84 mbobra 1.15     int i = 0;
  85                 int j = 0;
  86                 int count_mask = 0;
  87                 double sum = 0.0;
  88                 double err = 0.0;
  89 mbobra 1.14     *absFlux = 0.0;
  90                 *mean_vf_ptr = 0.0;
  91 xudong 1.27     
  92                 
  93 xudong 1.1      if (nx <= 0 || ny <= 0) return 1;
  94 xudong 1.27     
  95             	for (i = 0; i < nx; i++)
  96 xudong 1.1  	{
  97 mbobra 1.34 	   for (j = 0; j < ny; j++)
  98             	   {
  99 xudong 1.27             if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 100                         if isnan(bz[j * nx + i]) continue;
 101                         sum += (fabs(bz[j * nx + i]));
 102                         err += bz_err[j * nx + i]*bz_err[j * nx + i];
 103                         count_mask++;
 104 mbobra 1.34 	   }
 105 xudong 1.1  	}
 106 xudong 1.27     
 107                 *mean_vf_ptr     = sum*cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0;
 108                 *mean_vf_err_ptr = (sqrt(err))*fabs(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0); // error in the unsigned flux
 109                 *count_mask_ptr  = count_mask;
 110                 return 0;
 111 xudong 1.1  }
 112             
 113             /*===========================================*/
 114 mbobra 1.9  /* Example function 2: Calculate Bh, the horizontal field, in units of Gauss */
 115 xudong 1.1  // Native units of Bh are Gauss
 116             
 117 xudong 1.27 int computeBh(float *bx_err, float *by_err, float *bh_err, float *bx, float *by, float *bz, float *bh, int *dims,
 118 mbobra 1.3  			  float *mean_hf_ptr, int *mask, int *bitmask)
 119 xudong 1.1  
 120             {
 121 xudong 1.27     
 122 mbobra 1.14     int nx = dims[0];
 123                 int ny = dims[1];
 124 mbobra 1.15     int i = 0;
 125 xudong 1.27     int j = 0;
 126 mbobra 1.15     int count_mask = 0;
 127 xudong 1.27     double sum = 0.0;
 128 mbobra 1.9      *mean_hf_ptr = 0.0;
 129 xudong 1.27     
 130 xudong 1.1      if (nx <= 0 || ny <= 0) return 1;
 131 xudong 1.27     
 132             	for (i = 0; i < nx; i++)
 133                 {
 134 mbobra 1.5  	    for (j = 0; j < ny; j++)
 135 xudong 1.27         {
 136                         if isnan(bx[j * nx + i])
 137                         {
 138                             bh[j * nx + i] = NAN;
 139                             bh_err[j * nx + i] = NAN;
 140                             continue;
 141                         }
 142                         if isnan(by[j * nx + i])
 143                         {
 144                             bh[j * nx + i] = NAN;
 145                             bh_err[j * nx + i] = NAN;
 146                             continue;
 147                         }
 148                         bh[j * nx + i] = sqrt( bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] );
 149                         sum += bh[j * nx + i];
 150                         bh_err[j * nx + i]=sqrt( bx[j * nx + i]*bx[j * nx + i]*bx_err[j * nx + i]*bx_err[j * nx + i] + by[j * nx + i]*by[j * nx + i]*by_err[j * nx + i]*by_err[j * nx + i])/ bh[j * nx + i];
 151                         count_mask++;
 152                     }
 153                 }
 154                 
 155 xudong 1.1      *mean_hf_ptr = sum/(count_mask); // would be divided by nx*ny if shape of count_mask = shape of magnetogram
 156 xudong 1.27     
 157 xudong 1.1      return 0;
 158             }
 159             
 160             /*===========================================*/
 161             /* Example function 3: Calculate Gamma in units of degrees */
 162             // Native units of atan(x) are in radians; to convert from radians to degrees, multiply by (180./PI)
 163 xudong 1.27 //
 164 mbobra 1.20 // Error analysis calculations are done in radians (since derivatives are only true in units of radians),
 165             // and multiplied by (180./PI) at the end for consistency in units.
 166 xudong 1.1  
 167 mbobra 1.9  int computeGamma(float *bz_err, float *bh_err, float *bx, float *by, float *bz, float *bh, int *dims,
 168                              float *mean_gamma_ptr, float *mean_gamma_err_ptr, int *mask, int *bitmask)
 169 xudong 1.1  {
 170 mbobra 1.14     int nx = dims[0];
 171                 int ny = dims[1];
 172 mbobra 1.15     int i = 0;
 173                 int j = 0;
 174                 int count_mask = 0;
 175                 double sum = 0.0;
 176                 double err = 0.0;
 177                 *mean_gamma_ptr = 0.0;
 178 xudong 1.27     
 179 xudong 1.1      if (nx <= 0 || ny <= 0) return 1;
 180 xudong 1.27     
 181             	for (i = 0; i < nx; i++)
 182                 {
 183             	    for (j = 0; j < ny; j++)
 184                     {
 185                         if (bh[j * nx + i] > 100)
 186                         {
 187                             if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 188                             if isnan(bz[j * nx + i]) continue;
 189                             if isnan(bz_err[j * nx + i]) continue;
 190                             if isnan(bh_err[j * nx + i]) continue;
 191                             if isnan(bh[j * nx + i]) continue;
 192                             if (bz[j * nx + i] == 0) continue;
 193                             sum += fabs(atan(bh[j * nx + i]/fabs(bz[j * nx + i])))*(180./PI);
 194                             err += (1/(1+((bh[j * nx + i]*bh[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i]))))*(1/(1+((bh[j * nx + i]*bh[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i])))) *
 195                             ( ((bh_err[j * nx + i]*bh_err[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i])) +
 196                              ((bh[j * nx + i]*bh[j * nx + i]*bz_err[j * nx + i]*bz_err[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i]*bz[j * nx + i]*bz[j * nx + i])) );
 197                             count_mask++;
 198                         }
 199                     }
 200                 }
 201 xudong 1.27     
 202                 *mean_gamma_ptr = sum/count_mask;
 203                 *mean_gamma_err_ptr = (sqrt(err)/(count_mask))*(180./PI);
 204                 //printf("MEANGAM=%f\n",*mean_gamma_ptr);
 205                 //printf("MEANGAM_err=%f\n",*mean_gamma_err_ptr);
 206                 return 0;
 207 xudong 1.1  }
 208             
 209             /*===========================================*/
 210             /* Example function 4: Calculate B_Total*/
 211             // Native units of B_Total are in gauss
 212             
 213 mbobra 1.9  int computeB_total(float *bx_err, float *by_err, float *bz_err, float *bt_err, float *bx, float *by, float *bz, float *bt, int *dims, int *mask, int *bitmask)
 214 xudong 1.1  {
 215 xudong 1.27     
 216 mbobra 1.14     int nx = dims[0];
 217                 int ny = dims[1];
 218 mbobra 1.15     int i = 0;
 219                 int j = 0;
 220                 int count_mask = 0;
 221 xudong 1.1  	
 222                 if (nx <= 0 || ny <= 0) return 1;
 223 xudong 1.27     
 224             	for (i = 0; i < nx; i++)
 225                 {
 226             	    for (j = 0; j < ny; j++)
 227                     {
 228                         if isnan(bx[j * nx + i])
 229                         {
 230                             bt[j * nx + i] = NAN;
 231                             bt_err[j * nx + i] = NAN;
 232                             continue;
 233                         }
 234                         if isnan(by[j * nx + i])
 235                         {
 236                             bt[j * nx + i] = NAN;
 237                             bt_err[j * nx + i] = NAN;
 238                             continue;
 239                         }
 240                         if isnan(bz[j * nx + i])
 241                         {
 242                             bt[j * nx + i] = NAN;
 243                             bt_err[j * nx + i] = NAN;
 244 xudong 1.27                 continue;
 245                         }
 246                         bt[j * nx + i] = sqrt( bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] + bz[j * nx + i]*bz[j * nx + i]);
 247                         bt_err[j * nx + i]=sqrt(bx[j * nx + i]*bx[j * nx + i]*bx_err[j * nx + i]*bx_err[j * nx + i] + by[j * nx + i]*by[j * nx + i]*by_err[j * nx + i]*by_err[j * nx + i] +  bz[j * nx + i]*bz[j * nx + i]*bz_err[j * nx + i]*bz_err[j * nx + i] ) / bt[j * nx + i];
 248                     }
 249                 }
 250                 return 0;
 251 xudong 1.1  }
 252             
 253             /*===========================================*/
 254             /* Example function 5:  Derivative of B_Total SQRT( (dBt/dx)^2 + (dBt/dy)^2 ) */
 255             
 256 mbobra 1.37 int computeBtotalderivative(float *bt, int *dims, float *mean_derivative_btotal_ptr, int *mask, int *bitmask, float *derx_bt, float *dery_bt, float *bt_err, float *mean_derivative_btotal_err_ptr, float *err_termAt, float *err_termBt)
 257 xudong 1.1  {
 258 xudong 1.27     
 259 mbobra 1.14     int nx = dims[0];
 260                 int ny = dims[1];
 261 mbobra 1.15     int i = 0;
 262                 int j = 0;
 263                 int count_mask = 0;
 264 xudong 1.27     double sum = 0.0;
 265 mbobra 1.15     double err = 0.0;
 266 mbobra 1.14     *mean_derivative_btotal_ptr = 0.0;
 267 xudong 1.27     
 268 xudong 1.1      if (nx <= 0 || ny <= 0) return 1;
 269 xudong 1.27     
 270                 /* brute force method of calculating the derivative (no consideration for edges) */
 271                 for (i = 1; i <= nx-2; i++)
 272                 {
 273 mbobra 1.34 	for (j = 0; j <= ny-1; j++)
 274 xudong 1.27         {
 275 mbobra 1.34            derx_bt[j * nx + i] = (bt[j * nx + i+1] - bt[j * nx + i-1])*0.5;
 276 mbobra 1.37            err_termAt[j * nx + i] = (((bt[j * nx + (i+1)]-bt[j * nx + (i-1)])*(bt[j * nx + (i+1)]-bt[j * nx + (i-1)])) * (bt_err[j * nx + (i+1)]*bt_err[j * nx + (i+1)] + bt_err[j * nx + (i-1)]*bt_err[j * nx + (i-1)])) ;
 277 xudong 1.27         }
 278                 }
 279                 
 280                 /* brute force method of calculating the derivative (no consideration for edges) */
 281                 for (i = 0; i <= nx-1; i++)
 282                 {
 283 mbobra 1.34 	for (j = 1; j <= ny-2; j++)
 284 xudong 1.27         {
 285 mbobra 1.34            dery_bt[j * nx + i] = (bt[(j+1) * nx + i] - bt[(j-1) * nx + i])*0.5;
 286 mbobra 1.37            err_termBt[j * nx + i] = (((bt[(j+1) * nx + i]-bt[(j-1) * nx + i])*(bt[(j+1) * nx + i]-bt[(j-1) * nx + i])) * (bt_err[(j+1) * nx + i]*bt_err[(j+1) * nx + i] + bt_err[(j-1) * nx + i]*bt_err[(j-1) * nx + i])) ;
 287 xudong 1.27         }
 288                 }
 289                 
 290 mbobra 1.35     /* consider the edges for the arrays that contribute to the variable "sum" in the computation below.
 291                 ignore the edges for the error terms as those arrays have been initialized to zero. 
 292                 this is okay because the error term will ultimately not include the edge pixels as they are selected out by the mask and bitmask arrays.*/
 293 xudong 1.27     i=0;
 294                 for (j = 0; j <= ny-1; j++)
 295                 {
 296                     derx_bt[j * nx + i] = ( (-3*bt[j * nx + i]) + (4*bt[j * nx + (i+1)]) - (bt[j * nx + (i+2)]) )*0.5;
 297                 }
 298                 
 299                 i=nx-1;
 300                 for (j = 0; j <= ny-1; j++)
 301                 {
 302                     derx_bt[j * nx + i] = ( (3*bt[j * nx + i]) + (-4*bt[j * nx + (i-1)]) - (-bt[j * nx + (i-2)]) )*0.5;
 303                 }
 304                 
 305                 j=0;
 306                 for (i = 0; i <= nx-1; i++)
 307                 {
 308                     dery_bt[j * nx + i] = ( (-3*bt[j*nx + i]) + (4*bt[(j+1) * nx + i]) - (bt[(j+2) * nx + i]) )*0.5;
 309                 }
 310                 
 311                 j=ny-1;
 312                 for (i = 0; i <= nx-1; i++)
 313                 {
 314 xudong 1.27         dery_bt[j * nx + i] = ( (3*bt[j * nx + i]) + (-4*bt[(j-1) * nx + i]) - (-bt[(j-2) * nx + i]) )*0.5;
 315                 }
 316 mbobra 1.34 
 317                 // Calculate the sum only
 318 xudong 1.27     for (i = 1; i <= nx-2; i++)
 319                 {
 320                     for (j = 1; j <= ny-2; j++)
 321                     {
 322                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 323                         if ( (derx_bt[j * nx + i] + dery_bt[j * nx + i]) == 0) continue;
 324                         if isnan(bt[j * nx + i])      continue;
 325                         if isnan(bt[(j+1) * nx + i])  continue;
 326                         if isnan(bt[(j-1) * nx + i])  continue;
 327                         if isnan(bt[j * nx + i-1])    continue;
 328                         if isnan(bt[j * nx + i+1])    continue;
 329                         if isnan(bt_err[j * nx + i])  continue;
 330                         if isnan(derx_bt[j * nx + i]) continue;
 331                         if isnan(dery_bt[j * nx + i]) continue;
 332                         sum += sqrt( derx_bt[j * nx + i]*derx_bt[j * nx + i]  + dery_bt[j * nx + i]*dery_bt[j * nx + i]  ); /* Units of Gauss */
 333 mbobra 1.37             err += err_termBt[j * nx + i] / (16.0*( derx_bt[j * nx + i]*derx_bt[j * nx + i]  + dery_bt[j * nx + i]*dery_bt[j * nx + i]  ))+
 334                                err_termAt[j * nx + i] / (16.0*( derx_bt[j * nx + i]*derx_bt[j * nx + i]  + dery_bt[j * nx + i]*dery_bt[j * nx + i]  )) ;
 335 xudong 1.27             count_mask++;
 336                     }
 337                 }
 338                 
 339                 *mean_derivative_btotal_ptr     = (sum)/(count_mask);
 340                 *mean_derivative_btotal_err_ptr = (sqrt(err))/(count_mask);
 341                 //printf("MEANGBT=%f\n",*mean_derivative_btotal_ptr);
 342                 //printf("MEANGBT_err=%f\n",*mean_derivative_btotal_err_ptr);
 343                 
 344                 return 0;
 345 xudong 1.1  }
 346             
 347             
 348             /*===========================================*/
 349             /* Example function 6:  Derivative of Bh SQRT( (dBh/dx)^2 + (dBh/dy)^2 ) */
 350             
 351 mbobra 1.37 int computeBhderivative(float *bh, float *bh_err, int *dims, float *mean_derivative_bh_ptr, float *mean_derivative_bh_err_ptr, int *mask, int *bitmask, float *derx_bh, float *dery_bh, float *err_termAh, float *err_termBh)
 352 xudong 1.1  {
 353 xudong 1.27     
 354                 int nx = dims[0];
 355                 int ny = dims[1];
 356                 int i = 0;
 357                 int j = 0;
 358                 int count_mask = 0;
 359                 double sum= 0.0;
 360                 double err =0.0;
 361                 *mean_derivative_bh_ptr = 0.0;
 362                 
 363                 if (nx <= 0 || ny <= 0) return 1;
 364                 
 365                 /* brute force method of calculating the derivative (no consideration for edges) */
 366                 for (i = 1; i <= nx-2; i++)
 367                 {
 368 mbobra 1.34 	for (j = 0; j <= ny-1; j++)
 369 xudong 1.27         {
 370 mbobra 1.34            derx_bh[j * nx + i] = (bh[j * nx + i+1] - bh[j * nx + i-1])*0.5;
 371 mbobra 1.37            err_termAh[j * nx + i] = (((bh[j * nx + (i+1)]-bh[j * nx + (i-1)])*(bh[j * nx + (i+1)]-bh[j * nx + (i-1)])) * (bh_err[j * nx + (i+1)]*bh_err[j * nx + (i+1)] + bh_err[j * nx + (i-1)]*bh_err[j * nx + (i-1)]));
 372 xudong 1.27         }
 373                 }
 374                 
 375                 /* brute force method of calculating the derivative (no consideration for edges) */
 376                 for (i = 0; i <= nx-1; i++)
 377                 {
 378 mbobra 1.34        for (j = 1; j <= ny-2; j++)
 379                    {
 380                       dery_bh[j * nx + i] = (bh[(j+1) * nx + i] - bh[(j-1) * nx + i])*0.5;
 381 mbobra 1.37           err_termBh[j * nx + i] = (((bh[ (j+1) * nx + i]-bh[(j-1) * nx + i])*(bh[(j+1) * nx + i]-bh[(j-1) * nx + i])) * (bh_err[(j+1) * nx + i]*bh_err[(j+1) * nx + i] + bh_err[(j-1) * nx + i]*bh_err[(j-1) * nx + i]));
 382 mbobra 1.34        }
 383 xudong 1.27     }
 384                 
 385 mbobra 1.35     /* consider the edges for the arrays that contribute to the variable "sum" in the computation below.
 386                 ignore the edges for the error terms as those arrays have been initialized to zero. 
 387                 this is okay because the error term will ultimately not include the edge pixels as they are selected out by the mask and bitmask arrays.*/
 388 xudong 1.27     i=0;
 389                 for (j = 0; j <= ny-1; j++)
 390                 {
 391                     derx_bh[j * nx + i] = ( (-3*bh[j * nx + i]) + (4*bh[j * nx + (i+1)]) - (bh[j * nx + (i+2)]) )*0.5;
 392                 }
 393                 
 394                 i=nx-1;
 395                 for (j = 0; j <= ny-1; j++)
 396                 {
 397                     derx_bh[j * nx + i] = ( (3*bh[j * nx + i]) + (-4*bh[j * nx + (i-1)]) - (-bh[j * nx + (i-2)]) )*0.5;
 398                 }
 399                 
 400                 j=0;
 401                 for (i = 0; i <= nx-1; i++)
 402                 {
 403                     dery_bh[j * nx + i] = ( (-3*bh[j*nx + i]) + (4*bh[(j+1) * nx + i]) - (bh[(j+2) * nx + i]) )*0.5;
 404                 }
 405                 
 406                 j=ny-1;
 407                 for (i = 0; i <= nx-1; i++)
 408                 {
 409 xudong 1.27         dery_bh[j * nx + i] = ( (3*bh[j * nx + i]) + (-4*bh[(j-1) * nx + i]) - (-bh[(j-2) * nx + i]) )*0.5;
 410                 }
 411                 
 412                 
 413                 for (i = 0; i <= nx-1; i++)
 414                 {
 415                     for (j = 0; j <= ny-1; j++)
 416                     {
 417                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 418                         if ( (derx_bh[j * nx + i] + dery_bh[j * nx + i]) == 0) continue;
 419                         if isnan(bh[j * nx + i])      continue;
 420                         if isnan(bh[(j+1) * nx + i])  continue;
 421                         if isnan(bh[(j-1) * nx + i])  continue;
 422                         if isnan(bh[j * nx + i-1])    continue;
 423                         if isnan(bh[j * nx + i+1])    continue;
 424                         if isnan(bh_err[j * nx + i])  continue;
 425                         if isnan(derx_bh[j * nx + i]) continue;
 426                         if isnan(dery_bh[j * nx + i]) continue;
 427                         sum += sqrt( derx_bh[j * nx + i]*derx_bh[j * nx + i]  + dery_bh[j * nx + i]*dery_bh[j * nx + i]  ); /* Units of Gauss */
 428 mbobra 1.37             err += err_termBh[j * nx + i] / (16.0*( derx_bh[j * nx + i]*derx_bh[j * nx + i]  + dery_bh[j * nx + i]*dery_bh[j * nx + i]  ))+
 429                                err_termAh[j * nx + i] / (16.0*( derx_bh[j * nx + i]*derx_bh[j * nx + i]  + dery_bh[j * nx + i]*dery_bh[j * nx + i]  )) ;
 430 xudong 1.27             count_mask++;
 431                     }
 432                 }
 433                 
 434                 *mean_derivative_bh_ptr     = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
 435                 *mean_derivative_bh_err_ptr = (sqrt(err))/(count_mask); // error in the quantity (sum)/(count_mask)
 436                 //printf("MEANGBH=%f\n",*mean_derivative_bh_ptr);
 437                 //printf("MEANGBH_err=%f\n",*mean_derivative_bh_err_ptr);
 438                 
 439                 return 0;
 440 xudong 1.1  }
 441             
 442             /*===========================================*/
 443             /* Example function 7:  Derivative of B_vertical SQRT( (dBz/dx)^2 + (dBz/dy)^2 ) */
 444             
 445 mbobra 1.37 int computeBzderivative(float *bz, float *bz_err, int *dims, float *mean_derivative_bz_ptr, float *mean_derivative_bz_err_ptr, int *mask, int *bitmask, float *derx_bz, float *dery_bz, float *err_termA, float *err_termB)
 446 xudong 1.1  {
 447 xudong 1.27     
 448                 int nx = dims[0];
 449                 int ny = dims[1];
 450                 int i = 0;
 451                 int j = 0;
 452                 int count_mask = 0;
 453 mbobra 1.34     double sum = 0.0;
 454 xudong 1.27     double err = 0.0;
 455 mbobra 1.34     *mean_derivative_bz_ptr = 0.0;
 456 xudong 1.27     
 457 mbobra 1.34     if (nx <= 0 || ny <= 0) return 1;
 458 xudong 1.27     
 459                 /* brute force method of calculating the derivative (no consideration for edges) */
 460                 for (i = 1; i <= nx-2; i++)
 461                 {
 462 mbobra 1.34 	for (j = 0; j <= ny-1; j++)
 463 xudong 1.27         {
 464 mbobra 1.34            derx_bz[j * nx + i] = (bz[j * nx + i+1] - bz[j * nx + i-1])*0.5;
 465 mbobra 1.37            err_termA[j * nx + i] = (((bz[j * nx + (i+1)]-bz[j * nx + (i-1)])*(bz[j * nx + (i+1)]-bz[j * nx + (i-1)])) * (bz_err[j * nx + (i+1)]*bz_err[j * nx + (i+1)] + bz_err[j * nx + (i-1)]*bz_err[j * nx + (i-1)]));
 466 xudong 1.27         }
 467                 }
 468                 
 469                 /* brute force method of calculating the derivative (no consideration for edges) */
 470                 for (i = 0; i <= nx-1; i++)
 471                 {
 472 mbobra 1.34         for (j = 1; j <= ny-2; j++)
 473 xudong 1.27         {
 474 mbobra 1.34            dery_bz[j * nx + i] = (bz[(j+1) * nx + i] - bz[(j-1) * nx + i])*0.5;
 475 mbobra 1.37            err_termB[j * nx + i] = (((bz[(j+1) * nx + i]-bz[(j-1) * nx + i])*(bz[(j+1) * nx + i]-bz[(j-1) * nx + i])) * (bz_err[(j+1) * nx + i]*bz_err[(j+1) * nx + i] + bz_err[(j-1) * nx + i]*bz_err[(j-1) * nx + i]));
 476 xudong 1.27         }
 477                 }
 478                 
 479 mbobra 1.34     /* consider the edges for the arrays that contribute to the variable "sum" in the computation below.
 480 mbobra 1.35     ignore the edges for the error terms as those arrays have been initialized to zero. 
 481 mbobra 1.34     this is okay because the error term will ultimately not include the edge pixels as they are selected out by the mask and bitmask arrays.*/
 482 xudong 1.27     i=0;
 483                 for (j = 0; j <= ny-1; j++)
 484                 {
 485                     derx_bz[j * nx + i] = ( (-3*bz[j * nx + i]) + (4*bz[j * nx + (i+1)]) - (bz[j * nx + (i+2)]) )*0.5;
 486                 }
 487                 
 488                 i=nx-1;
 489                 for (j = 0; j <= ny-1; j++)
 490                 {
 491                     derx_bz[j * nx + i] = ( (3*bz[j * nx + i]) + (-4*bz[j * nx + (i-1)]) - (-bz[j * nx + (i-2)]) )*0.5;
 492                 }
 493                 
 494                 j=0;
 495                 for (i = 0; i <= nx-1; i++)
 496                 {
 497                     dery_bz[j * nx + i] = ( (-3*bz[j*nx + i]) + (4*bz[(j+1) * nx + i]) - (bz[(j+2) * nx + i]) )*0.5;
 498                 }
 499                 
 500                 j=ny-1;
 501                 for (i = 0; i <= nx-1; i++)
 502                 {
 503 xudong 1.27         dery_bz[j * nx + i] = ( (3*bz[j * nx + i]) + (-4*bz[(j-1) * nx + i]) - (-bz[(j-2) * nx + i]) )*0.5;
 504                 }
 505                 
 506                 
 507                 for (i = 0; i <= nx-1; i++)
 508                 {
 509                     for (j = 0; j <= ny-1; j++)
 510                     {
 511                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 512                         if ( (derx_bz[j * nx + i] + dery_bz[j * nx + i]) == 0) continue;
 513                         if isnan(bz[j * nx + i])      continue;
 514                         if isnan(bz[(j+1) * nx + i])  continue;
 515                         if isnan(bz[(j-1) * nx + i])  continue;
 516                         if isnan(bz[j * nx + i-1])    continue;
 517                         if isnan(bz[j * nx + i+1])    continue;
 518                         if isnan(bz_err[j * nx + i])  continue;
 519                         if isnan(derx_bz[j * nx + i]) continue;
 520                         if isnan(dery_bz[j * nx + i]) continue;
 521 mbobra 1.34             sum += sqrt( derx_bz[j * nx + i]*derx_bz[j * nx + i]  + dery_bz[j * nx + i]*dery_bz[j * nx + i] ); /* Units of Gauss */
 522 mbobra 1.37             err += err_termB[j * nx + i] / (16.0*( derx_bz[j * nx + i]*derx_bz[j * nx + i]  + dery_bz[j * nx + i]*dery_bz[j * nx + i]  )) +
 523                                err_termA[j * nx + i] / (16.0*( derx_bz[j * nx + i]*derx_bz[j * nx + i]  + dery_bz[j * nx + i]*dery_bz[j * nx + i]  )) ;
 524 xudong 1.27             count_mask++;
 525                     }
 526                 }
 527                 
 528 mbobra 1.34     *mean_derivative_bz_ptr = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
 529 xudong 1.27     *mean_derivative_bz_err_ptr = (sqrt(err))/(count_mask); // error in the quantity (sum)/(count_mask)
 530                 //printf("MEANGBZ=%f\n",*mean_derivative_bz_ptr);
 531                 //printf("MEANGBZ_err=%f\n",*mean_derivative_bz_err_ptr);
 532                 
 533 xudong 1.1  	return 0;
 534             }
 535             
 536             /*===========================================*/
 537             /* Example function 8:  Current Jz = (dBy/dx) - (dBx/dy) */
 538             
 539             //  In discretized space like data pixels,
 540             //  the current (or curl of B) is calculated as
 541             //  the integration of the field Bx and By along
 542             //  the circumference of the data pixel divided by the area of the pixel.
 543             //  One form of differencing (a word for the differential operator
 544 xudong 1.27 //  in the discretized space) of the curl is expressed as
 545 xudong 1.1  //  (dx * (Bx(i,j-1)+Bx(i,j)) / 2
 546             //  +dy * (By(i+1,j)+By(i,j)) / 2
 547             //  -dx * (Bx(i,j+1)+Bx(i,j)) / 2
 548 xudong 1.27 //  -dy * (By(i-1,j)+By(i,j)) / 2) / (dx * dy)
 549             //
 550 xudong 1.1  //
 551             //  To change units from Gauss/pixel to mA/m^2 (the units for Jz in Leka and Barnes, 2003),
 552             //  one must perform the following unit conversions:
 553 mbobra 1.8  //  (Gauss)(1/arcsec)(arcsec/meter)(Newton/Gauss*Ampere*meter)(Ampere^2/Newton)(milliAmpere/Ampere), or
 554             //  (Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(1 T / 10^4 Gauss)(1 / 4*PI*10^-7)( 10^3 milliAmpere/Ampere), or
 555 xudong 1.27 //  (Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(0.00010)(1/MUNAUGHT)(1000.),
 556 xudong 1.1  //  where a Tesla is represented as a Newton/Ampere*meter.
 557 mbobra 1.4  //
 558 xudong 1.1  //  As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
 559             //  In that case, we would have the following:
 560             //  (Gauss/pix)(1/0.5)(1/722500)(10^-4)(4*PI*10^7)(10^3), or
 561             //  jz * (35.0)
 562             //
 563             //  The units of total unsigned vertical current (us_i) are simply in A. In this case, we would have the following:
 564 mbobra 1.8  //  (Gauss/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF)(0.00010)(1/MUNAUGHT)(CDELT1)(CDELT1)(RSUN_REF/RSUN_OBS)(RSUN_REF/RSUN_OBS)
 565             //  = (Gauss/pix)(0.00010)(1/MUNAUGHT)(CDELT1)(RSUN_REF/RSUN_OBS)
 566 xudong 1.1  
 567             
 568 xudong 1.27 // Comment out random number generator, which can only run on solar3
 569 mbobra 1.33 // int computeJz(float *bx_err, float *by_err, float *bx, float *by, int *dims, float *jz, float *jz_err, float *jz_err_squared,
 570 xudong 1.27 //	      int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery, float *noisebx,
 571 mbobra 1.9  //              float *noiseby, float *noisebz)
 572             
 573             int computeJz(float *bx_err, float *by_err, float *bx, float *by, int *dims, float *jz, float *jz_err, float *jz_err_squared,
 574 mbobra 1.33               int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery, float *err_term1, float *err_term2)
 575 mbobra 1.9  
 576 xudong 1.1  
 577 xudong 1.27 {
 578                 int nx = dims[0];
 579                 int ny = dims[1];
 580                 int i = 0;
 581                 int j = 0;
 582                 int count_mask = 0;
 583                 
 584             	if (nx <= 0 || ny <= 0) return 1;
 585                 
 586                 /* Calculate the derivative*/
 587                 /* brute force method of calculating the derivative (no consideration for edges) */
 588                 
 589                 for (i = 1; i <= nx-2; i++)
 590                 {
 591 mbobra 1.34 	for (j = 0; j <= ny-1; j++)
 592 xudong 1.27         {
 593 mbobra 1.34            derx[j * nx + i]      = (by[j * nx + i+1] - by[j * nx + i-1])*0.5;
 594                        err_term1[j * nx + i] = (by_err[j * nx + i+1])*(by_err[j * nx + i+1]) + (by_err[j * nx + i-1])*(by_err[j * nx + i-1]);
 595 xudong 1.27         }
 596                 }
 597                 
 598                 for (i = 0; i <= nx-1; i++)
 599                 {
 600 mbobra 1.34 	for (j = 1; j <= ny-2; j++)
 601 xudong 1.27         {
 602 mbobra 1.34            dery[j * nx + i]      = (bx[(j+1) * nx + i] - bx[(j-1) * nx + i])*0.5;
 603                        err_term2[j * nx + i] = (bx_err[(j+1) * nx + i])*(bx_err[(j+1) * nx + i]) + (bx_err[(j-1) * nx + i])*(bx_err[(j-1) * nx + i]);
 604 xudong 1.27         }
 605                 }
 606 mbobra 1.33 
 607 mbobra 1.35     /* consider the edges for the arrays that contribute to the variable "sum" in the computation below.
 608                 ignore the edges for the error terms as those arrays have been initialized to zero. 
 609                 this is okay because the error term will ultimately not include the edge pixels as they are selected out by the mask and bitmask arrays.*/
 610             
 611 xudong 1.27     i=0;
 612                 for (j = 0; j <= ny-1; j++)
 613                 {
 614 mbobra 1.33         derx[j * nx + i]      = ( (-3*by[j * nx + i]) + (4*by[j * nx + (i+1)]) - (by[j * nx + (i+2)]) )*0.5;
 615 xudong 1.27     }
 616                 
 617                 i=nx-1;
 618                 for (j = 0; j <= ny-1; j++)
 619                 {
 620 mbobra 1.33         derx[j * nx + i]      = ( (3*by[j * nx + i]) + (-4*by[j * nx + (i-1)]) - (-by[j * nx + (i-2)]) )*0.5;
 621 xudong 1.27     }
 622                 
 623                 j=0;
 624                 for (i = 0; i <= nx-1; i++)
 625                 {
 626 mbobra 1.33         dery[j * nx + i]      = ( (-3*bx[j*nx + i]) + (4*bx[(j+1) * nx + i]) - (bx[(j+2) * nx + i]) )*0.5;
 627 xudong 1.27     }
 628                 
 629                 j=ny-1;
 630                 for (i = 0; i <= nx-1; i++)
 631                 {
 632 mbobra 1.33         dery[j * nx + i]      = ( (3*bx[j * nx + i]) + (-4*bx[(j-1) * nx + i]) - (-bx[(j-2) * nx + i]) )*0.5;
 633 xudong 1.27     }
 634 mbobra 1.33 
 635 xudong 1.27     
 636 mbobra 1.33     for (i = 0; i <= nx-1; i++)
 637 xudong 1.27     {
 638 mbobra 1.33         for (j = 0; j <= ny-1; j++)
 639 xudong 1.27         {
 640 mbobra 1.33             // calculate jz at all points         
 641 xudong 1.27             jz[j * nx + i]            = (derx[j * nx + i]-dery[j * nx + i]);       // jz is in units of Gauss/pix
 642 mbobra 1.33             jz_err[j * nx + i]        = 0.5*sqrt( err_term1[j * nx + i] + err_term2[j * nx + i] ) ;
 643 xudong 1.27             jz_err_squared[j * nx + i]= (jz_err[j * nx + i]*jz_err[j * nx + i]);
 644 mbobra 1.33             count_mask++;            
 645 xudong 1.27         }
 646                 }
 647             	return 0;
 648             }
 649 mbobra 1.33  
 650 mbobra 1.5  /*===========================================*/
 651             
 652 mbobra 1.11 /* Example function 9:  Compute quantities on Jz array */
 653 xudong 1.27 // Compute mean and total current on Jz array.
 654 mbobra 1.6  
 655 mbobra 1.9  int computeJzsmooth(float *bx, float *by, int *dims, float *jz, float *jz_smooth, float *jz_err, float *jz_rms_err, float *jz_err_squared_smooth,
 656 xudong 1.27                     float *mean_jz_ptr, float *mean_jz_err_ptr, float *us_i_ptr, float *us_i_err_ptr, int *mask, int *bitmask,
 657 mbobra 1.9                      float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery)
 658 mbobra 1.5  
 659             {
 660 xudong 1.27     
 661                 int nx = dims[0];
 662                 int ny = dims[1];
 663                 int i = 0;
 664                 int j = 0;
 665                 int count_mask = 0;
 666 mbobra 1.15 	double curl = 0.0;
 667 xudong 1.27     double us_i = 0.0;
 668                 double err = 0.0;
 669                 
 670 mbobra 1.5  	if (nx <= 0 || ny <= 0) return 1;
 671 xudong 1.27     
 672                 /* At this point, use the smoothed Jz array with a Gaussian (FWHM of 4 pix and truncation width of 12 pixels) but keep the original array dimensions*/
 673                 for (i = 0; i <= nx-1; i++)
 674                 {
 675                     for (j = 0; j <= ny-1; j++)
 676                     {
 677                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 678                         if isnan(derx[j * nx + i]) continue;
 679                         if isnan(dery[j * nx + i]) continue;
 680                         if isnan(jz[j * nx + i]) continue;
 681                         curl +=     (jz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref)*(0.00010)*(1/MUNAUGHT)*(1000.); /* curl is in units of mA / m^2 */
 682                         us_i += fabs(jz[j * nx + i])*(cdelt1/1)*(rsun_ref/rsun_obs)*(0.00010)*(1/MUNAUGHT);         /* us_i is in units of A */
 683                         err  += (jz_err[j * nx + i]*jz_err[j * nx + i]);
 684                         count_mask++;
 685                     }
 686                 }
 687                 
 688                 /* Calculate mean vertical current density (mean_jz) and total unsigned vertical current (us_i) using smoothed Jz array and continue conditions above */
 689                 *mean_jz_ptr     = curl/(count_mask);        /* mean_jz gets populated as MEANJZD */
 690                 *mean_jz_err_ptr = (sqrt(err)/count_mask)*((1/cdelt1)*(rsun_obs/rsun_ref)*(0.00010)*(1/MUNAUGHT)*(1000.)); // error in the quantity MEANJZD
 691                 
 692 xudong 1.27     *us_i_ptr        = (us_i);                   /* us_i gets populated as TOTUSJZ */
 693                 *us_i_err_ptr    = (sqrt(err))*((cdelt1/1)*(rsun_ref/rsun_obs)*(0.00010)*(1/MUNAUGHT)); // error in the quantity TOTUSJZ
 694                 
 695                 //printf("MEANJZD=%f\n",*mean_jz_ptr);
 696                 //printf("MEANJZD_err=%f\n",*mean_jz_err_ptr);
 697                 
 698                 //printf("TOTUSJZ=%g\n",*us_i_ptr);
 699                 //printf("TOTUSJZ_err=%g\n",*us_i_err_ptr);
 700                 
 701 xudong 1.1  	return 0;
 702 xudong 1.27     
 703 xudong 1.1  }
 704             
 705 mbobra 1.5  /*===========================================*/
 706             
 707             /* Example function 10:  Twist Parameter, alpha */
 708 xudong 1.1  
 709 mbobra 1.5  // The twist parameter, alpha, is defined as alpha = Jz/Bz. In this case, the calculation
 710 mbobra 1.19 // for alpha is weighted by Bz (following Hagino et al., http://adsabs.harvard.edu/abs/2004PASJ...56..831H):
 711 xudong 1.27 
 712             // numerator   = sum of all Jz*Bz
 713             // denominator = sum of Bz*Bz
 714             // alpha       = numerator/denominator
 715 mbobra 1.6  
 716 mbobra 1.5  // The units of alpha are in 1/Mm
 717 xudong 1.1  // The units of Jz are in Gauss/pix; the units of Bz are in Gauss.
 718             //
 719 xudong 1.27 // Therefore, the units of Jz/Bz = (Gauss/pix)(1/Gauss)(pix/arcsec)(arsec/meter)(meter/Mm), or
 720 xudong 1.1  //                               = (Gauss/pix)(1/Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(10^6)
 721             //                               = 1/Mm
 722             
 723 mbobra 1.9  int computeAlpha(float *jz_err, float *bz_err, float *bz, int *dims, float *jz, float *jz_smooth, float *mean_alpha_ptr, float *mean_alpha_err_ptr, int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
 724 mbobra 1.5  
 725 xudong 1.1  {
 726 xudong 1.27     int nx                     = dims[0];
 727                 int ny                     = dims[1];
 728                 int i                      = 0;
 729                 int j                      = 0;
 730 mbobra 1.19 	double alpha_total         = 0.0;
 731 xudong 1.27     double C                   = ((1/cdelt1)*(rsun_obs/rsun_ref)*(1000000.));
 732                 double total               = 0.0;
 733                 double A                   = 0.0;
 734                 double B                   = 0.0;
 735                 
 736 xudong 1.1  	if (nx <= 0 || ny <= 0) return 1;
 737 xudong 1.27 	for (i = 1; i < nx-1; i++)
 738                 {
 739             	    for (j = 1; j < ny-1; j++)
 740                     {
 741                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 742                         if isnan(jz[j * nx + i])   continue;
 743                         if isnan(bz[j * nx + i])   continue;
 744                         if (jz[j * nx + i] == 0.0) continue;
 745                         if (bz[j * nx + i] == 0.0) continue;
 746                         A += jz[j*nx+i]*bz[j*nx+i];
 747                         B += bz[j*nx+i]*bz[j*nx+i];
 748                     }
 749                 }
 750                 
 751             	for (i = 1; i < nx-1; i++)
 752                 {
 753             	    for (j = 1; j < ny-1; j++)
 754                     {
 755                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 756                         if isnan(jz[j * nx + i])   continue;
 757                         if isnan(bz[j * nx + i])   continue;
 758 xudong 1.27             if (jz[j * nx + i] == 0.0) continue;
 759                         if (bz[j * nx + i] == 0.0) continue;
 760                         total += bz[j*nx+i]*bz[j*nx+i]*jz_err[j*nx+i]*jz_err[j*nx+i] + (jz[j*nx+i]-2*bz[j*nx+i]*A/B)*(jz[j*nx+i]-2*bz[j*nx+i]*A/B)*bz_err[j*nx+i]*bz_err[j*nx+i];
 761                     }
 762                 }
 763                 
 764                 /* Determine the absolute value of alpha. The units for alpha are 1/Mm */
 765                 alpha_total              = ((A/B)*C);
 766                 *mean_alpha_ptr          = alpha_total;
 767                 *mean_alpha_err_ptr      = (C/B)*(sqrt(total));
 768                 
 769 xudong 1.1  	return 0;
 770             }
 771             
 772             /*===========================================*/
 773 mbobra 1.9  /* Example function 11:  Helicity (mean current helicty, total unsigned current helicity, absolute value of net current helicity) */
 774 xudong 1.1  
 775             //  The current helicity is defined as Bz*Jz and the units are G^2 / m
 776             //  The units of Jz are in G/pix; the units of Bz are in G.
 777 xudong 1.27 //  Therefore, the units of Bz*Jz = (Gauss)*(Gauss/pix) = (Gauss^2/pix)(pix/arcsec)(arcsec/meter)
 778             //                                                      = (Gauss^2/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF)
 779 mbobra 1.9  //                                                      =  G^2 / m.
 780 xudong 1.1  
 781 xudong 1.27 int computeHelicity(float *jz_err, float *jz_rms_err, float *bz_err, float *bz, int *dims, float *jz, float *mean_ih_ptr,
 782                                 float *mean_ih_err_ptr, float *total_us_ih_ptr, float *total_abs_ih_ptr,
 783 mbobra 1.9                      float *total_us_ih_err_ptr, float *total_abs_ih_err_ptr, int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
 784 xudong 1.1  
 785             {
 786 xudong 1.27     
 787                 int nx         = dims[0];
 788                 int ny         = dims[1];
 789                 int i          = 0;
 790                 int j          = 0;
 791                 int count_mask = 0;
 792 mbobra 1.20 	double sum     = 0.0;
 793             	double sum2    = 0.0;
 794             	double err     = 0.0;
 795 xudong 1.1  	
 796             	if (nx <= 0 || ny <= 0) return 1;
 797 xudong 1.27     
 798             	for (i = 0; i < nx; i++)
 799 xudong 1.1  	{
 800 xudong 1.27 		for (j = 0; j < ny; j++)
 801 xudong 1.1  		{
 802 xudong 1.27             if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 803                         if isnan(jz[j * nx + i])     continue;
 804                         if isnan(bz[j * nx + i])     continue;
 805                         if isnan(jz_err[j * nx + i]) continue;
 806                         if isnan(bz_err[j * nx + i]) continue;
 807                         if (bz[j * nx + i] == 0.0)   continue;
 808                         if (jz[j * nx + i] == 0.0)   continue;
 809                         sum     +=     (jz[j * nx + i]*bz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref); // contributes to MEANJZH and ABSNJZH
 810                         sum2    += fabs(jz[j * nx + i]*bz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref); // contributes to TOTUSJH
 811                         err     += (jz_err[j * nx + i]*jz_err[j * nx + i]*bz[j * nx + i]*bz[j * nx + i]) + (bz_err[j * nx + i]*bz_err[j * nx + i]*jz[j * nx + i]*jz[j * nx + i]);
 812                         count_mask++;
 813                     }
 814                 }
 815                 
 816             	*mean_ih_ptr          = sum/count_mask ; /* Units are G^2 / m ; keyword is MEANJZH */
 817 mbobra 1.9  	*total_us_ih_ptr      = sum2           ; /* Units are G^2 / m ; keyword is TOTUSJH */
 818             	*total_abs_ih_ptr     = fabs(sum)      ; /* Units are G^2 / m ; keyword is ABSNJZH */
 819 xudong 1.27     
 820                 *mean_ih_err_ptr      = (sqrt(err)/count_mask)*(1/cdelt1)*(rsun_obs/rsun_ref) ; // error in the quantity MEANJZH
 821                 *total_us_ih_err_ptr  = (sqrt(err))*(1/cdelt1)*(rsun_obs/rsun_ref) ;            // error in the quantity TOTUSJH
 822                 *total_abs_ih_err_ptr = (sqrt(err))*(1/cdelt1)*(rsun_obs/rsun_ref) ;            // error in the quantity ABSNJZH
 823                 
 824                 //printf("MEANJZH=%f\n",*mean_ih_ptr);
 825                 //printf("MEANJZH_err=%f\n",*mean_ih_err_ptr);
 826                 
 827                 //printf("TOTUSJH=%f\n",*total_us_ih_ptr);
 828                 //printf("TOTUSJH_err=%f\n",*total_us_ih_err_ptr);
 829                 
 830                 //printf("ABSNJZH=%f\n",*total_abs_ih_ptr);
 831                 //printf("ABSNJZH_err=%f\n",*total_abs_ih_err_ptr);
 832                 
 833 xudong 1.1  	return 0;
 834             }
 835             
 836             /*===========================================*/
 837 mbobra 1.5  /* Example function 12:  Sum of Absolute Value per polarity  */
 838 xudong 1.1  
 839             //  The Sum of the Absolute Value per polarity is defined as the following:
 840 mbobra 1.36 //  fabs(sum(jz gt 0)) + fabs(sum(jz lt 0)) and the units are in Amperes per square arcsecond.
 841 xudong 1.1  //  The units of jz are in G/pix. In this case, we would have the following:
 842             //  Jz = (Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)(RSUN_REF/RSUN_OBS)(RSUN_OBS/RSUN_REF),
 843             //     = (Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)
 844 mbobra 1.9  //
 845             //  The error in this quantity is the same as the error in the mean vertical current (mean_jz_err).
 846 xudong 1.1  
 847 xudong 1.27 int computeSumAbsPerPolarity(float *jz_err, float *bz_err, float *bz, float *jz, int *dims, float *totaljzptr, float *totaljz_err_ptr,
 848 mbobra 1.3  							 int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
 849 xudong 1.1  
 850 xudong 1.27 {
 851                 int nx = dims[0];
 852                 int ny = dims[1];
 853                 int i=0;
 854                 int j=0;
 855                 int count_mask=0;
 856 mbobra 1.32     double sum1=0.0;
 857 xudong 1.27     double sum2=0.0;
 858                 double err=0.0;
 859 mbobra 1.33     *totaljzptr=0.0;
 860 xudong 1.27     
 861 mbobra 1.33     if (nx <= 0 || ny <= 0) return 1;
 862 xudong 1.27     
 863 mbobra 1.33     for (i = 0; i < nx; i++)
 864 xudong 1.27     {
 865 mbobra 1.33 	 for (j = 0; j < ny; j++)
 866 xudong 1.27         {
 867                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 868                         if isnan(bz[j * nx + i]) continue;
 869                         if isnan(jz[j * nx + i]) continue;
 870                         if (bz[j * nx + i] >  0) sum1 += ( jz[j * nx + i])*(1/cdelt1)*(0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs);
 871                         if (bz[j * nx + i] <= 0) sum2 += ( jz[j * nx + i])*(1/cdelt1)*(0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs);
 872                         err += (jz_err[j * nx + i]*jz_err[j * nx + i]);
 873                         count_mask++;
 874                     }
 875                 }
 876 xudong 1.1  	
 877 mbobra 1.32     *totaljzptr    = fabs(sum1) + fabs(sum2);  /* Units are Amperes per arcsecond */
 878 xudong 1.27     *totaljz_err_ptr = sqrt(err)*(1/cdelt1)*fabs((0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs));
 879                 //printf("SAVNCPP=%g\n",*totaljzptr);
 880                 //printf("SAVNCPP_err=%g\n",*totaljz_err_ptr);
 881                 
 882 mbobra 1.33     return 0;
 883 xudong 1.1  }
 884             
 885             /*===========================================*/
 886 mbobra 1.5  /* Example function 13:  Mean photospheric excess magnetic energy and total photospheric excess magnetic energy density */
 887 xudong 1.1  // The units for magnetic energy density in cgs are ergs per cubic centimeter. The formula B^2/8*PI integrated over all space, dV
 888 xudong 1.27 // automatically yields erg per cubic centimeter for an input B in Gauss. Note that the 8*PI can come out of the integral; thus,
 889             // the integral is over B^2 dV and the 8*PI is divided at the end.
 890 xudong 1.1  //
 891             // Total magnetic energy is the magnetic energy density times dA, or the area, and the units are thus ergs/cm. To convert
 892             // ergs per centimeter cubed to ergs per centimeter, simply multiply by the area per pixel in cm:
 893 mbobra 1.9  //   erg/cm^3*(CDELT1^2)*(RSUN_REF/RSUN_OBS ^2)*(100.^2)
 894             // = erg/cm^3*(0.5 arcsec/pix)^2(722500m/arcsec)^2(100cm/m)^2
 895             // = erg/cm^3*(1.30501e15)
 896 xudong 1.1  // = erg/cm(1/pix^2)
 897             
 898 xudong 1.27 int computeFreeEnergy(float *bx_err, float *by_err, float *bx, float *by, float *bpx, float *bpy, int *dims,
 899                                   float *meanpotptr, float *meanpot_err_ptr, float *totpotptr, float *totpot_err_ptr, int *mask, int *bitmask,
 900 xudong 1.1  					  float cdelt1, double rsun_ref, double rsun_obs)
 901             
 902             {
 903 xudong 1.27     int nx = dims[0];
 904                 int ny = dims[1];
 905                 int i = 0;
 906                 int j = 0;
 907                 int count_mask = 0;
 908 mbobra 1.31     double sum = 0.0;
 909 xudong 1.27     double sum1 = 0.0;
 910                 double err = 0.0;
 911                 *totpotptr = 0.0;
 912 mbobra 1.31     *meanpotptr = 0.0;
 913 xudong 1.27     
 914 mbobra 1.31     if (nx <= 0 || ny <= 0) return 1;
 915 xudong 1.27     
 916 mbobra 1.31     for (i = 0; i < nx; i++)
 917 xudong 1.27     {
 918 mbobra 1.31 	for (j = 0; j < ny; j++)
 919 xudong 1.27         {
 920                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 921                         if isnan(bx[j * nx + i]) continue;
 922                         if isnan(by[j * nx + i]) continue;
 923                         sum  += ( ((bx[j * nx + i] - bpx[j * nx + i])*(bx[j * nx + i] - bpx[j * nx + i])) + ((by[j * nx + i] - bpy[j * nx + i])*(by[j * nx + i] - bpy[j * nx + i])) )*(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0);
 924                         sum1 += (  ((bx[j * nx + i] - bpx[j * nx + i])*(bx[j * nx + i] - bpx[j * nx + i])) + ((by[j * nx + i] - bpy[j * nx + i])*(by[j * nx + i] - bpy[j * nx + i])) );
 925                         err  += 4.0*(bx[j * nx + i] - bpx[j * nx + i])*(bx[j * nx + i] - bpx[j * nx + i])*(bx_err[j * nx + i]*bx_err[j * nx + i]) +
 926                         4.0*(by[j * nx + i] - bpy[j * nx + i])*(by[j * nx + i] - bpy[j * nx + i])*(by_err[j * nx + i]*by_err[j * nx + i]);
 927                         count_mask++;
 928                     }
 929                 }
 930                 
 931                 /* Units of meanpotptr are ergs per centimeter */
 932 mbobra 1.20 	*meanpotptr      = (sum1) / (count_mask*8.*PI) ;     /* Units are ergs per cubic centimeter */
 933 xudong 1.27     *meanpot_err_ptr = (sqrt(err)) / (count_mask*8.*PI); // error in the quantity (sum)/(count_mask)
 934                 
 935                 /* Units of sum are ergs/cm^3, units of factor are cm^2/pix^2; therefore, units of totpotptr are ergs per centimeter */
 936                 *totpotptr       = (sum)/(8.*PI);
 937                 *totpot_err_ptr  = (sqrt(err))*fabs(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0*(1/(8.*PI)));
 938                 
 939                 //printf("MEANPOT=%g\n",*meanpotptr);
 940                 //printf("MEANPOT_err=%g\n",*meanpot_err_ptr);
 941                 
 942                 //printf("TOTPOT=%g\n",*totpotptr);
 943                 //printf("TOTPOT_err=%g\n",*totpot_err_ptr);
 944                 
 945 mbobra 1.31     return 0;
 946 xudong 1.1  }
 947             
 948             /*===========================================*/
 949 mbobra 1.5  /* Example function 14:  Mean 3D shear angle, area with shear greater than 45, mean horizontal shear angle, area with horizontal shear angle greater than 45 */
 950 xudong 1.1  
 951 mbobra 1.20 int computeShearAngle(float *bx_err, float *by_err, float *bz_err, float *bx, float *by, float *bz, float *bpx, float *bpy, float *bpz, int *dims,
 952 mbobra 1.9                        float *meanshear_angleptr, float *meanshear_angle_err_ptr, float *area_w_shear_gt_45ptr, int *mask, int *bitmask)
 953 mbobra 1.21 
 954             
 955 xudong 1.27 {
 956                 int nx = dims[0];
 957                 int ny = dims[1];
 958                 int i = 0;
 959                 int j = 0;
 960                 float count_mask = 0;
 961                 float count = 0;
 962                 double dotproduct = 0.0;
 963                 double magnitude_potential = 0.0;
 964                 double magnitude_vector = 0.0;
 965                 double shear_angle = 0.0;
 966                 double denominator = 0.0;
 967                 double term1 = 0.0;
 968                 double term2 = 0.0;
 969                 double term3 = 0.0;
 970                 double sumsum = 0.0;
 971                 double err = 0.0;
 972                 double part1 = 0.0;
 973                 double part2 = 0.0;
 974                 double part3 = 0.0;
 975                 *area_w_shear_gt_45ptr = 0.0;
 976 mbobra 1.31     *meanshear_angleptr = 0.0;
 977 xudong 1.1  	
 978 mbobra 1.31     if (nx <= 0 || ny <= 0) return 1;
 979 xudong 1.27     
 980 mbobra 1.31     for (i = 0; i < nx; i++)
 981 xudong 1.27     {
 982 mbobra 1.31 	for (j = 0; j < ny; j++)
 983 xudong 1.27         {
 984                         if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 985                         if isnan(bpx[j * nx + i]) continue;
 986                         if isnan(bpy[j * nx + i]) continue;
 987                         if isnan(bpz[j * nx + i]) continue;
 988                         if isnan(bz[j * nx + i]) continue;
 989                         if isnan(bx[j * nx + i]) continue;
 990                         if isnan(by[j * nx + i]) continue;
 991                         if isnan(bx_err[j * nx + i]) continue;
 992                         if isnan(by_err[j * nx + i]) continue;
 993                         if isnan(bz_err[j * nx + i]) continue;
 994                         
 995                         /* For mean 3D shear angle, percentage with shear greater than 45*/
 996                         dotproduct            = (bpx[j * nx + i])*(bx[j * nx + i]) + (bpy[j * nx + i])*(by[j * nx + i]) + (bpz[j * nx + i])*(bz[j * nx + i]);
 997                         magnitude_potential   = sqrt( (bpx[j * nx + i]*bpx[j * nx + i]) + (bpy[j * nx + i]*bpy[j * nx + i]) + (bpz[j * nx + i]*bpz[j * nx + i]));
 998                         magnitude_vector      = sqrt( (bx[j * nx + i]*bx[j * nx + i])   + (by[j * nx + i]*by[j * nx + i])   + (bz[j * nx + i]*bz[j * nx + i]) );
 999                         //printf("dotproduct=%f\n",dotproduct);
1000                         //printf("magnitude_potential=%f\n",magnitude_potential);
1001                         //printf("magnitude_vector=%f\n",magnitude_vector);
1002                         
1003                         shear_angle            = acos(dotproduct/(magnitude_potential*magnitude_vector))*(180./PI);
1004 xudong 1.27             sumsum                  += shear_angle;
1005                         //printf("shear_angle=%f\n",shear_angle);
1006                         count ++;
1007                         
1008                         if (shear_angle > 45) count_mask ++;
1009                         
1010                         // For the error analysis
1011                         
1012                         term1 = bx[j * nx + i]*by[j * nx + i]*bpy[j * nx + i] - by[j * nx + i]*by[j * nx + i]*bpx[j * nx + i] + bz[j * nx + i]*bx[j * nx + i]*bpz[j * nx + i] - bz[j * nx + i]*bz[j * nx + i]*bpx[j * nx + i];
1013                         term2 = bx[j * nx + i]*bx[j * nx + i]*bpy[j * nx + i] - bx[j * nx + i]*by[j * nx + i]*bpx[j * nx + i] + bx[j * nx + i]*bz[j * nx + i]*bpy[j * nx + i] - bz[j * nx + i]*by[j * nx + i]*bpz[j * nx + i];
1014                         term3 = bx[j * nx + i]*bx[j * nx + i]*bpz[j * nx + i] - bx[j * nx + i]*bz[j * nx + i]*bpx[j * nx + i] + by[j * nx + i]*by[j * nx + i]*bpz[j * nx + i] - by[j * nx + i]*bz[j * nx + i]*bpy[j * nx + i];
1015                         
1016                         part1 = bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] + bz[j * nx + i]*bz[j * nx + i];
1017                         part2 = bpx[j * nx + i]*bpx[j * nx + i] + bpy[j * nx + i]*bpy[j * nx + i] + bpz[j * nx + i]*bpz[j * nx + i];
1018                         part3 = bx[j * nx + i]*bpx[j * nx + i] + by[j * nx + i]*bpy[j * nx + i] + bz[j * nx + i]*bpz[j * nx + i];
1019                         
1020                         // denominator is squared
1021                         denominator = part1*part1*part1*part2*(1.0-((part3*part3)/(part1*part2)));
1022                         
1023                         err = (term1*term1*bx_err[j * nx + i]*bx_err[j * nx + i])/(denominator) +
1024                         (term1*term1*bx_err[j * nx + i]*bx_err[j * nx + i])/(denominator) +
1025 xudong 1.27             (term1*term1*bx_err[j * nx + i]*bx_err[j * nx + i])/(denominator) ;
1026                         
1027                     }
1028                 }
1029                 /* For mean 3D shear angle, area with shear greater than 45*/
1030                 *meanshear_angleptr = (sumsum)/(count);                 /* Units are degrees */
1031 mbobra 1.39     
1032                 // For the error in the mean 3D shear angle:
1033                 // If count_mask is 0, then we run into a divide by zero error. In this case, set *meanshear_angle_err_ptr to NAN
1034                 // If count_mask is greater than zero, then compute the error.
1035                 if (count_mask == 0)
1036                     *meanshear_angle_err_ptr = NAN;
1037                 else
1038                     *meanshear_angle_err_ptr = (sqrt(err)/count_mask)*(180./PI);
1039 xudong 1.27     
1040                 /* The area here is a fractional area -- the % of the total area. This has no error associated with it. */
1041                 *area_w_shear_gt_45ptr   = (count_mask/(count))*(100.0);
1042                 
1043                 //printf("MEANSHR=%f\n",*meanshear_angleptr);
1044 mbobra 1.39     //printf("ERRMSHA=%f\n",*meanshear_angle_err_ptr);
1045 xudong 1.27     //printf("SHRGT45=%f\n",*area_w_shear_gt_45ptr);
1046 mbobra 1.39     return 0;
1047 xudong 1.27 }
1048 xudong 1.1  
1049 xudong 1.27 /*===========================================*/
1050 mbobra 1.29 /* Example function 15: R parameter as defined in Schrijver, 2007 */
1051             //
1052             // Note that there is a restriction on the function fsample()
1053             // If the following occurs:
1054             //      nx_out > floor((ny_in-1)/scale + 1) 
1055             //      ny_out > floor((ny_in-1)/scale + 1),
1056             // where n*_out are the dimensions of the output array and n*_in 
1057             // are the dimensions of the input array, fsample() will usually result 
1058             // in a segfault (though not always, depending on how the segfault was accessed.) 
1059             
1060 xudong 1.27 int computeR(float *bz_err, float *los, int *dims, float *Rparam, float cdelt1,
1061                          float *rim, float *p1p0, float *p1n0, float *p1p, float *p1n, float *p1,
1062 mbobra 1.30              float *pmap, int nx1, int ny1, 
1063                          int scale, float *p1pad, int nxp, int nyp, float *pmapn)
1064             
1065 mbobra 1.29 { 
1066 xudong 1.27     int nx = dims[0];
1067                 int ny = dims[1];
1068                 int i = 0;
1069                 int j = 0;
1070 mbobra 1.30     int index, index1;
1071 xudong 1.27     double sum = 0.0;
1072                 double err = 0.0;
1073                 *Rparam = 0.0;
1074                 struct fresize_struct fresboxcar, fresgauss;
1075 mbobra 1.30     struct fint_struct fints;
1076 xudong 1.27     float sigma = 10.0/2.3548;
1077                 
1078 mbobra 1.30     // set up convolution kernels
1079 xudong 1.27     init_fresize_boxcar(&fresboxcar,1,1);
1080                 init_fresize_gaussian(&fresgauss,sigma,20,1);
1081 mbobra 1.29 
1082 mbobra 1.30     // =============== [STEP 1] =============== 
1083                 // bin the line-of-sight magnetogram down by a factor of scale 
1084 xudong 1.27     fsample(los, rim, nx, ny, nx, nx1, ny1, nx1, scale, 0, 0, 0.0);
1085 mbobra 1.29 
1086 mbobra 1.30     // =============== [STEP 2] =============== 
1087                 // identify positive and negative pixels greater than +/- 150 gauss
1088                 // and label those pixels with a 1.0 in arrays p1p0 and p1n0
1089 xudong 1.27     for (i = 0; i < nx1; i++)
1090                 {
1091                     for (j = 0; j < ny1; j++)
1092                     {
1093                         index = j * nx1 + i;
1094                         if (rim[index] > 150)
1095                             p1p0[index]=1.0;
1096                         else
1097                             p1p0[index]=0.0;
1098                         if (rim[index] < -150)
1099                             p1n0[index]=1.0;
1100                         else
1101                             p1n0[index]=0.0;
1102                     }
1103                 }
1104 mbobra 1.30 
1105                 // =============== [STEP 3] =============== 
1106                 // smooth each of the negative and positive pixel bitmaps      
1107 xudong 1.27     fresize(&fresboxcar, p1p0, p1p, nx1, ny1, nx1, nx1, ny1, nx1, 0, 0, 0.0);
1108                 fresize(&fresboxcar, p1n0, p1n, nx1, ny1, nx1, nx1, ny1, nx1, 0, 0, 0.0);
1109 mbobra 1.30 
1110                 // =============== [STEP 4] =============== 
1111                 // find the pixels for which p1p and p1n are both equal to 1. 
1112                 // this defines the polarity inversion line
1113 xudong 1.27     for (i = 0; i < nx1; i++)
1114                 {
1115                     for (j = 0; j < ny1; j++)
1116                     {
1117                         index = j * nx1 + i;
1118 mbobra 1.30             if ((p1p[index] > 0.0) && (p1n[index] > 0.0))
1119 xudong 1.27                 p1[index]=1.0;
1120                         else
1121                             p1[index]=0.0;
1122                     }
1123                 }
1124 mbobra 1.30 
1125                 // pad p1 with zeroes so that the gaussian colvolution in step 5
1126                 // does not cut off data within hwidth of the edge
1127                
1128                 // step i: zero p1pad
1129                 for (i = 0; i < nxp; i++)
1130                 {
1131                     for (j = 0; j < nyp; j++)
1132                     {
1133                         index = j * nxp + i;
1134                         p1pad[index]=0.0;
1135                     }
1136                 }
1137             
1138                 // step ii: place p1 at the center of p1pad
1139                 for (i = 0; i < nx1; i++)
1140                 {
1141                    for (j = 0; j < ny1; j++)
1142                    {
1143                         index  = j * nx1 + i; 
1144                         index1 = (j+20) * nxp + (i+20);
1145 mbobra 1.30             p1pad[index1]=p1[index];
1146                     }
1147                 }
1148             
1149                 // =============== [STEP 5] =============== 
1150                 // convolve the polarity inversion line map with a gaussian
1151                 // to identify the region near the plarity inversion line
1152                 // the resultant array is called pmap
1153                 fresize(&fresgauss, p1pad, pmap, nxp, nyp, nxp, nxp, nyp, nxp, 0, 0, 0.0);
1154             
1155             
1156                // select out the nx1 x ny1 non-padded array  within pmap
1157                 for (i = 0; i < nx1; i++)
1158                 {
1159                    for (j = 0; j < ny1; j++)
1160                    {
1161                         index  = j * nx1 + i; 
1162                         index1 = (j+20) * nxp + (i+20);
1163                         pmapn[index]=pmap[index1];
1164                     }
1165                 }
1166 mbobra 1.30 
1167                 // =============== [STEP 6] =============== 
1168                 // the R parameter is calculated
1169 xudong 1.27     for (i = 0; i < nx1; i++)
1170                 {
1171                     for (j = 0; j < ny1; j++)
1172                     {
1173                         index = j * nx1 + i;
1174 mbobra 1.32             if isnan(pmapn[index]) continue;
1175                         if isnan(rim[index]) continue;
1176 mbobra 1.30             sum += pmapn[index]*abs(rim[index]);
1177 xudong 1.27         }
1178                 }
1179                 
1180                 if (sum < 1.0)
1181                     *Rparam = 0.0;
1182                 else
1183                     *Rparam = log10(sum);
1184 mbobra 1.30 
1185 mbobra 1.32     //printf("R_VALUE=%f\n",*Rparam);
1186             
1187 xudong 1.27     free_fresize(&fresboxcar);
1188                 free_fresize(&fresgauss);
1189 mbobra 1.30 
1190 xudong 1.27     return 0;
1191 mbobra 1.30 
1192 xudong 1.1  }
1193             
1194 mbobra 1.31 /*===========================================*/
1195             /* Example function 16: Lorentz force as defined in Fisher, 2012 */
1196             // 
1197             // This calculation is adapted from Xudong's code
1198             // at /proj/cgem/lorentz/apps/lorentz.c 
1199             
1200             int computeLorentz(float *bx,  float *by, float *bz, float *fx, float *fy, float *fz, int *dims, 
1201                                float *totfx_ptr, float *totfy_ptr, float *totfz_ptr, float *totbsq_ptr,
1202                                float *epsx_ptr, float *epsy_ptr, float *epsz_ptr, int *mask, int *bitmask,
1203                                float cdelt1, double rsun_ref, double rsun_obs)
1204             
1205             { 
1206             
1207                 int nx = dims[0];
1208                 int ny = dims[1];
1209                 int nxny = nx*ny;
1210                 int j = 0;
1211                 int index;
1212                 double totfx = 0, totfy = 0, totfz = 0;
1213                 double bsq = 0, totbsq = 0;
1214                 double epsx = 0, epsy = 0, epsz = 0;
1215 mbobra 1.31     double area = cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0;
1216                 double k_h = -1.0 * area / (4. * PI) / 1.0e20;
1217                 double k_z = area / (8. * PI) / 1.0e20;
1218             
1219                 if (nx <= 0 || ny <= 0) return 1;        
1220             
1221                 for (int i = 0; i < nxny; i++) 
1222                 {  
1223                    if ( mask[i] < 70 || bitmask[i] < 30 ) continue;
1224                    if isnan(bx[i]) continue;
1225                    if isnan(by[i]) continue;
1226                    if isnan(bz[i]) continue;
1227 mbobra 1.32        fx[i]  = bx[i] * bz[i] * k_h;
1228                    fy[i]  = by[i] * bz[i] * k_h;
1229 mbobra 1.31        fz[i]  = (bx[i] * bx[i] + by[i] * by[i] - bz[i] * bz[i]) * k_z;
1230                    bsq    = bx[i] * bx[i] + by[i] * by[i] + bz[i] * bz[i];
1231                    totfx  += fx[i]; totfy += fy[i]; totfz += fz[i];
1232                    totbsq += bsq;
1233                 }
1234                
1235                 *totfx_ptr  = totfx;
1236                 *totfy_ptr  = totfy;
1237                 *totfz_ptr  = totfz;    
1238                 *totbsq_ptr = totbsq;  
1239                 *epsx_ptr   = (totfx / k_h) / totbsq;
1240                 *epsy_ptr   = (totfy / k_h) / totbsq;
1241                 *epsz_ptr   = (totfz / k_z) / totbsq;
1242             
1243 mbobra 1.32     //printf("TOTBSQ=%f\n",*totbsq_ptr);
1244             
1245 mbobra 1.31     return 0;
1246              
1247             }
1248             
1249 mbobra 1.38 /*===========================================*/
1250             
1251             /* Example function 17: Compute total unsigned flux in units of G/cm^2 on the LOS field */
1252             
1253             //  To compute the unsigned flux, we simply calculate
1254             //  flux = surface integral [(vector LOS) dot (normal vector)],
1255             //       = surface integral [(magnitude LOS)*(magnitude normal)*(cos theta)].
1256             //  However, since the field is radial, we will assume cos theta = 1.
1257             //  Therefore the pixels only need to be corrected for the projection.
1258             
1259             //  To convert G to G*cm^2, simply multiply by the number of square centimeters per pixel.
1260             //  As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
1261             //  (Gauss/pix^2)(CDELT1)^2(RSUN_REF/RSUN_OBS)^2(100.cm/m)^2
1262             //  =Gauss*cm^2
1263             
1264 mbobra 1.40 int computeAbsFlux_los(float *los, int *dims, float *absFlux_los,
1265                                    float *mean_vf_los_ptr, float *count_mask_los_ptr,
1266 mbobra 1.38                        int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
1267             
1268             {
1269                 
1270                 int nx = dims[0];
1271                 int ny = dims[1];
1272                 int i = 0;
1273                 int j = 0;
1274 mbobra 1.40     int count_mask_los = 0;
1275 mbobra 1.38     double sum = 0.0;
1276 mbobra 1.40     *absFlux_los = 0.0;
1277                 *mean_vf_los_ptr = 0.0;
1278 mbobra 1.38     
1279                  
1280                 if (nx <= 0 || ny <= 0) return 1;
1281                 
1282             	for (i = 0; i < nx; i++)
1283             	{
1284             	   for (j = 0; j < ny; j++)
1285             	   {
1286             	    if ( bitmask[j * nx + i] < 30 ) continue;
1287 mbobra 1.43             if isnan(los[j * nx + i]) continue;
1288 mbobra 1.38             sum += (fabs(los[j * nx + i]));
1289 mbobra 1.40             count_mask_los++;
1290 mbobra 1.38 	   }
1291             	}
1292                 
1293 mbobra 1.40     *mean_vf_los_ptr     = sum*cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0;
1294                 *count_mask_los_ptr  = count_mask_los;
1295             
1296 mbobra 1.42     //printf("USFLUXL=%f\n",*mean_vf_los_ptr);
1297                 //printf("CMASKL=%f\n",*count_mask_los_ptr);
1298 mbobra 1.38 
1299                 return 0;
1300             }
1301             
1302             /*===========================================*/
1303             /* Example function 18:  Derivative of B_LOS (approximately B_vertical) = SQRT( ( dLOS/dx )^2 + ( dLOS/dy )^2 ) */
1304             
1305             int computeLOSderivative(float *los, int *dims, float *mean_derivative_los_ptr, int *bitmask, float *derx_los, float *dery_los)
1306             {
1307                 
1308                 int nx = dims[0];
1309                 int ny = dims[1];
1310                 int i = 0;
1311                 int j = 0;
1312                 int count_mask = 0;
1313                 double sum = 0.0;
1314                 *mean_derivative_los_ptr = 0.0;
1315                 
1316                 if (nx <= 0 || ny <= 0) return 1;
1317                 
1318                 /* brute force method of calculating the derivative (no consideration for edges) */
1319 mbobra 1.38     for (i = 1; i <= nx-2; i++)
1320                 {
1321             	for (j = 0; j <= ny-1; j++)
1322                     {
1323                        derx_los[j * nx + i] = (los[j * nx + i+1] - los[j * nx + i-1])*0.5;
1324                     }
1325                 }
1326                 
1327                 /* brute force method of calculating the derivative (no consideration for edges) */
1328                 for (i = 0; i <= nx-1; i++)
1329                 {
1330                     for (j = 1; j <= ny-2; j++)
1331                     {
1332                        dery_los[j * nx + i] = (los[(j+1) * nx + i] - los[(j-1) * nx + i])*0.5;
1333                     }
1334                 }
1335                 
1336                 /* consider the edges for the arrays that contribute to the variable "sum" in the computation below.
1337                 ignore the edges for the error terms as those arrays have been initialized to zero. 
1338                 this is okay because the error term will ultimately not include the edge pixels as they are selected out by the mask and bitmask arrays.*/
1339                 i=0;
1340 mbobra 1.38     for (j = 0; j <= ny-1; j++)
1341                 {
1342                     derx_los[j * nx + i] = ( (-3*los[j * nx + i]) + (4*los[j * nx + (i+1)]) - (los[j * nx + (i+2)]) )*0.5;
1343                 }
1344                 
1345                 i=nx-1;
1346                 for (j = 0; j <= ny-1; j++)
1347                 {
1348                     derx_los[j * nx + i] = ( (3*los[j * nx + i]) + (-4*los[j * nx + (i-1)]) - (-los[j * nx + (i-2)]) )*0.5;
1349                 }
1350                 
1351                 j=0;
1352                 for (i = 0; i <= nx-1; i++)
1353                 {
1354                     dery_los[j * nx + i] = ( (-3*los[j*nx + i]) + (4*los[(j+1) * nx + i]) - (los[(j+2) * nx + i]) )*0.5;
1355                 }
1356                 
1357                 j=ny-1;
1358                 for (i = 0; i <= nx-1; i++)
1359                 {
1360                     dery_los[j * nx + i] = ( (3*los[j * nx + i]) + (-4*los[(j-1) * nx + i]) - (-los[(j-2) * nx + i]) )*0.5;
1361 mbobra 1.38     }
1362                 
1363                 
1364                 for (i = 0; i <= nx-1; i++)
1365                 {
1366                     for (j = 0; j <= ny-1; j++)
1367                     {
1368                         if ( bitmask[j * nx + i] < 30 ) continue;
1369                         if isnan(los[j * nx + i])      continue;
1370                         if isnan(los[(j+1) * nx + i])  continue;
1371                         if isnan(los[(j-1) * nx + i])  continue;
1372                         if isnan(los[j * nx + i-1])    continue;
1373                         if isnan(los[j * nx + i+1])    continue;
1374                         if isnan(derx_los[j * nx + i]) continue;
1375                         if isnan(dery_los[j * nx + i]) continue;
1376                         sum += sqrt( derx_los[j * nx + i]*derx_los[j * nx + i]  + dery_los[j * nx + i]*dery_los[j * nx + i] ); /* Units of Gauss */
1377                         count_mask++;
1378                     }
1379                 }
1380                 
1381                 *mean_derivative_los_ptr = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
1382 mbobra 1.40     
1383 mbobra 1.42     //printf("MEANGBL=%f\n",*mean_derivative_los_ptr);
1384 mbobra 1.38     
1385             	return 0;
1386             }
1387             
1388 xudong 1.1  /*==================KEIJI'S CODE =========================*/
1389             
1390             // #include <omp.h>
1391             #include <math.h>
1392             
1393             void greenpot(float *bx, float *by, float *bz, int nnx, int nny)
1394             {
1395 xudong 1.27     /* local workings */
1396                 int inx, iny, i, j, n;
1397                 /* local array */
1398                 float *pfpot, *rdist;
1399                 pfpot=(float *)malloc(sizeof(float) *nnx*nny);
1400                 rdist=(float *)malloc(sizeof(float) *nnx*nny);
1401                 float *bztmp;
1402                 bztmp=(float *)malloc(sizeof(float) *nnx*nny);
1403                 /* make nan */
1404                 //  unsigned long long llnan = 0x7ff0000000000000;
1405                 //  float NAN = (float)(llnan);
1406                 
1407                 // #pragma omp parallel for private (inx)
1408                 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){pfpot[nnx*iny+inx] = 0.0;}}
1409                 // #pragma omp parallel for private (inx)
1410                 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){rdist[nnx*iny+inx] = 0.0;}}
1411                 // #pragma omp parallel for private (inx)
1412                 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){bx[nnx*iny+inx] = 0.0;}}
1413                 // #pragma omp parallel for private (inx)
1414                 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){by[nnx*iny+inx] = 0.0;}}
1415                 // #pragma omp parallel for private (inx)
1416 xudong 1.27     for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++)
1417                 {
1418                     float val0 = bz[nnx*iny + inx];
1419                     if (isnan(val0)){bztmp[nnx*iny + inx] = 0.0;}else{bztmp[nnx*iny + inx] = val0;}
1420                 }}
1421                 
1422                 // dz is the monopole depth
1423                 float dz = 0.001;
1424                 
1425                 // #pragma omp parallel for private (inx)
1426                 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++)
1427                 {
1428                     float rdd, rdd1, rdd2;
1429                     float r;
1430                     rdd1 = (float)(inx);
1431                     rdd2 = (float)(iny);
1432                     rdd = rdd1 * rdd1 + rdd2 * rdd2 + dz * dz;
1433                     rdist[nnx*iny+inx] = 1.0/sqrt(rdd);
1434                 }}
1435                 
1436                 int iwindow;
1437 xudong 1.27     if (nnx > nny) {iwindow = nnx;} else {iwindow = nny;}
1438                 float rwindow;
1439                 rwindow = (float)(iwindow);
1440                 rwindow = rwindow * rwindow + 0.01; // must be of square
1441                 
1442                 rwindow = 1.0e2; // limit the window size to be 10.
1443                 
1444                 rwindow = sqrt(rwindow);
1445                 iwindow = (int)(rwindow);
1446                 
1447                 // #pragma omp parallel for private(inx)
1448                 for (iny=0;iny<nny;iny++){for (inx=0;inx<nnx;inx++)
1449 xudong 1.1      {
1450 xudong 1.27         float val0 = bz[nnx*iny + inx];
1451                     if (isnan(val0))
1452                     {
1453                         pfpot[nnx*iny + inx] = 0.0; // hmmm.. NAN;
1454                     }
1455                     else
1456                     {
1457                         float sum;
1458                         sum = 0.0;
1459                         int j2, i2;
1460                         int j2s, j2e, i2s, i2e;
1461                         j2s = iny - iwindow;
1462                         j2e = iny + iwindow;
1463                         if (j2s <   0){j2s =   0;}
1464                         if (j2e > nny){j2e = nny;}
1465                         i2s = inx - iwindow;
1466                         i2e = inx + iwindow;
1467                         if (i2s <   0){i2s =   0;}
1468 mbobra 1.37             if (i2e > nnx){i2e = nnx;}
1469                         
1470                         for (j2=j2s;j2<j2e;j2++){for (i2=i2s;i2<i2e;i2++)
1471                         {
1472 xudong 1.27                 float val1 = bztmp[nnx*j2 + i2];
1473 mbobra 1.37                 float rr, r1, r2;
1474                             //        r1 = (float)(i2 - inx);
1475                             //        r2 = (float)(j2 - iny);
1476                             //        rr = r1*r1 + r2*r2;
1477                             //        if (rr < rwindow)
1478                             //        {
1479 xudong 1.27                 int   di, dj;
1480                             di = abs(i2 - inx);
1481                             dj = abs(j2 - iny);
1482                             sum = sum + val1 * rdist[nnx * dj + di] * dz;
1483 mbobra 1.37                 //        }
1484 xudong 1.27             } }
1485                         pfpot[nnx*iny + inx] = sum; // Note that this is a simplified definition.
1486                     }
1487                 } } // end of OpenMP parallelism
1488                 
1489                 // #pragma omp parallel for private(inx)
1490                 for (iny=1; iny < nny - 1; iny++){for (inx=1; inx < nnx - 1; inx++)
1491 xudong 1.1      {
1492 xudong 1.27         bx[nnx*iny + inx] = -(pfpot[nnx*iny + (inx+1)]-pfpot[nnx*iny + (inx-1)]) * 0.5;
1493                     by[nnx*iny + inx] = -(pfpot[nnx*(iny+1) + inx]-pfpot[nnx*(iny-1) + inx]) * 0.5;
1494                 } } // end of OpenMP parallelism
1495 mbobra 1.37     
1496 xudong 1.27     free(rdist);
1497                 free(pfpot);
1498                 free(bztmp);
1499 xudong 1.1  } // end of void func. greenpot
1500             
1501             
1502             /*===========END OF KEIJI'S CODE =========================*/
1503 mbobra 1.14 
1504             char *sw_functions_version() // Returns CVS version of sw_functions.c
1505             {
1506 xudong 1.27     return strdup("$Id");
1507 mbobra 1.14 }
1508             
1509 xudong 1.1  /* ---------------- end of this file ----------------*/

Karen Tian
Powered by
ViewCVS 0.9.4