static int PyTabprm_cset( PyTabprm* self) { int status = 0; status = tabset(self->x); if (status == 0) { return 0; } else { wcslib_tab_to_python_exc(status); return -1; } }
char * tabspec(char const * string) { char const * set; char const * tab; while (isdigit(* string)) { for (set = string; isdigit(* string); string++); if (* string == '.') { string++; } for (tab = string; isdigit(* string); string++); if (* string == ',') { string++; } tabset (atoi(set), atoi(tab)); } return ((char *) (string)); }
int tabx2s( struct tabprm *tab, int ncoord, int nelem, const double x[], double world[], int stat[]) { static const char *function = "tabx2s"; int i, iv, k, *Km, m, M, n, nv, offset, p1, status; double *coord, *Psi, psi_m, upsilon, wgt; register int *statp; register const double *xp; register double *wp; struct wcserr **err; if (tab == 0x0) return TABERR_NULL_POINTER; err = &(tab->err); /* Initialize if required. */ if (tab->flag != TABSET) { if ((status = tabset(tab))) return status; } /* This is used a lot. */ M = tab->M; status = 0; xp = x; wp = world; statp = stat; for (n = 0; n < ncoord; n++) { /* Determine the indexes. */ Km = tab->K; for (m = 0; m < M; m++, Km++) { /* N.B. psi_m and Upsilon_m are 1-relative FITS indexes. */ i = tab->map[m]; psi_m = *(xp+i) + tab->crval[m]; Psi = tab->index[m]; if (Psi == 0x0) { /* Default indexing is simple. */ upsilon = psi_m; } else { /* To ease confusion, decrement Psi so that we can use 1-relative C array indexing to match the 1-relative FITS indexing. */ Psi--; if (*Km == 1) { /* Index vector is degenerate. */ if (Psi[1]-0.5 <= psi_m && psi_m <= Psi[1]+0.5) { upsilon = psi_m; } else { *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X)); goto next; } } else { /* Interpolate in the indexing vector. */ if (tab->sense[m] == 1) { /* Monotonic increasing index values. */ if (psi_m < Psi[1]) { if (Psi[1] - 0.5*(Psi[2]-Psi[1]) <= psi_m) { /* Allow minor extrapolation. */ k = 1; } else { /* Index is out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X)); goto next; } } else if (Psi[*Km] < psi_m) { if (psi_m <= Psi[*Km] + 0.5*(Psi[*Km]-Psi[*Km-1])) { /* Allow minor extrapolation. */ k = *Km - 1; } else { /* Index is out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X)); goto next; } } else { for (k = 1; k < *Km; k++) { if (psi_m < Psi[k]) { continue; } if (Psi[k] == psi_m && psi_m < Psi[k+1]) { break; } if (Psi[k] < psi_m && psi_m <= Psi[k+1]) { break; } } } } else { /* Monotonic decreasing index values. */ if (psi_m > Psi[1]) { if (Psi[1] + 0.5*(Psi[1]-Psi[2]) >= psi_m) { /* Allow minor extrapolation. */ k = 1; } else { /* Index is out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X)); goto next; } } else if (psi_m < Psi[*Km]) { if (Psi[*Km] - 0.5*(Psi[*Km-1]-Psi[*Km]) <= psi_m) { /* Allow minor extrapolation. */ k = *Km - 1; } else { /* Index is out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X)); goto next; } } else { for (k = 1; k < *Km; k++) { if (psi_m > Psi[k]) { continue; } if (Psi[k] == psi_m && psi_m > Psi[k+1]) { break; } if (Psi[k] > psi_m && psi_m >= Psi[k+1]) { break; } } } } upsilon = k + (psi_m - Psi[k]) / (Psi[k+1] - Psi[k]); } } if (upsilon < 0.5 || upsilon > *Km + 0.5) { /* Index out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_X)); goto next; } /* Fiducial array indices and fractional offset. p1 is 1-relative while tab::p0 is 0-relative. */ p1 = (int)floor(upsilon); tab->p0[m] = p1 - 1; tab->delta[m] = upsilon - p1; if (p1 == 0) { tab->p0[m] += 1; tab->delta[m] -= 1.0; } else if (p1 == *Km && *Km > 1) { tab->p0[m] -= 1; tab->delta[m] += 1.0; } } /* Now interpolate in the coordinate array; the M-dimensional linear */ /* interpolation algorithm is described in Sect. 3.4 of WCS Paper IV. */ for (m = 0; m < M; m++) { i = tab->map[m]; *(wp+i) = 0.0; } /* Loop over the 2^M vertices surrounding P. */ nv = 1 << M; for (iv = 0; iv < nv; iv++) { /* Locate vertex in the coordinate array and compute its weight. */ offset = 0; wgt = 1.0; for (m = M-1; m >= 0; m--) { offset *= tab->K[m]; offset += tab->p0[m]; if (iv & (1 << m)) { if (tab->K[m] > 1) offset++; wgt *= tab->delta[m]; } else { wgt *= 1.0 - tab->delta[m]; } } if (wgt == 0.0) continue; /* Add the contribution from this vertex to each element. */ coord = tab->coord + offset*M; for (m = 0; m < M; m++) { i = tab->map[m]; *(wp+i) += *(coord++) * wgt; } if (wgt == 1.0) break; } *statp = 0; next: xp += nelem; wp += nelem; statp++; } return status; }
int tabs2x( struct tabprm* tab, int ncoord, int nelem, const double world[], double x[], int stat[]) { static const char *function = "tabs2x"; int tabedge(struct tabprm *); int tabrow(struct tabprm *, const double *); int tabvox(struct tabprm *, const double *, int, double **, unsigned int *); int edge, i, ic, iv, k, *Km, M, m, n, nv, offset, status; double *dcrd, delta, *Psi, psi_m, **tabcoord, upsilon; register int *statp; register const double *wp; register double *xp; struct wcserr **err; if (tab == 0x0) return TABERR_NULL_POINTER; err = &(tab->err); /* Initialize if required. */ if (tab->flag != TABSET) { if ((status = tabset(tab))) return status; } /* This is used a lot. */ M = tab->M; tabcoord = 0x0; nv = 0; if (M > 1) { nv = 1 << M; tabcoord = calloc(nv, sizeof(double *)); } status = 0; wp = world; xp = x; statp = stat; for (n = 0; n < ncoord; n++) { /* Locate this coordinate in the coordinate array. */ edge = 0; for (m = 0; m < M; m++) { tab->p0[m] = 0; } for (ic = 0; ic < tab->nc; ic++) { if (tab->p0[0] == 0) { /* New row, could it contain a solution? */ if (edge || tabrow(tab, wp)) { /* No, skip it. */ ic += tab->K[0]; tab->p0[1]++; edge = tabedge(tab); /* Because ic will be incremented when the loop is reentered. */ ic--; continue; } } if (M == 1) { /* Deal with the one-dimensional case separately for efficiency. */ if (*wp == tab->coord[0]) { tab->p0[0] = 0; tab->delta[0] = 0.0; break; } else if (ic < tab->nc - 1) { if (((tab->coord[ic] <= *wp && *wp <= tab->coord[ic+1]) || (tab->coord[ic] >= *wp && *wp >= tab->coord[ic+1])) && (tab->index[0] == 0x0 || tab->index[0][ic] != tab->index[0][ic+1])) { tab->p0[0] = ic; tab->delta[0] = (*wp - tab->coord[ic]) / (tab->coord[ic+1] - tab->coord[ic]); break; } } } else { /* Multi-dimensional tables are harder. */ if (!edge) { /* Addresses of the coordinates for each corner of the "voxel". */ for (iv = 0; iv < nv; iv++) { offset = 0; for (m = M-1; m >= 0; m--) { offset *= tab->K[m]; offset += tab->p0[m]; if ((iv & (1 << m)) && (tab->K[m] > 1)) offset++; } tabcoord[iv] = tab->coord + offset*M; } if (tabvox(tab, wp, 0, tabcoord, 0x0) == 0) { /* Found a solution. */ break; } } /* Next voxel. */ tab->p0[0]++; edge = tabedge(tab); } } if (ic == tab->nc) { /* Coordinate not found; allow minor extrapolation. */ if (M == 1) { /* Should there be a solution? */ if (tab->extrema[0] <= *wp && *wp <= tab->extrema[1]) { dcrd = tab->coord; for (i = 0; i < 2; i++) { if (i) dcrd += tab->K[0] - 2; delta = (*wp - *dcrd) / (*(dcrd+1) - *dcrd); if (i == 0) { if (-0.5 <= delta && delta <= 0.0) { tab->p0[0] = 0; tab->delta[0] = delta; ic = 0; break; } } else { if (1.0 <= delta && delta <= 1.5) { tab->p0[0] = tab->K[0] - 1; tab->delta[0] = delta - 1.0; ic = 0; } } } } } else { /* Multi-dimensional tables. */ /* >>> TBD <<< */ } } if (ic == tab->nc) { /* Coordinate not found. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD)); } else { /* Determine the intermediate world coordinates. */ Km = tab->K; for (m = 0; m < M; m++, Km++) { /* N.B. Upsilon_m and psi_m are 1-relative FITS indexes. */ upsilon = (tab->p0[m] + 1) + tab->delta[m]; if (upsilon < 0.5 || upsilon > *Km + 0.5) { /* Index out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD)); } else { /* Do inverse lookup of the index vector. */ Psi = tab->index[m]; if (Psi == 0x0) { /* Default indexing. */ psi_m = upsilon; } else { /* Decrement Psi and use 1-relative C array indexing to match the 1-relative FITS indexing. */ Psi--; if (*Km == 1) { /* Degenerate index vector. */ psi_m = Psi[1]; } else { k = (int)(upsilon); psi_m = Psi[k]; if (k < *Km) { psi_m += (upsilon - k) * (Psi[k+1] - Psi[k]); } } } i = tab->map[m]; xp[i] = psi_m - tab->crval[m]; } } *statp = 0; } wp += nelem; xp += nelem; statp++; } if (tabcoord) free(tabcoord); return status; }