/** * Constructs the DataLink Parameters from an URL string containing a VOTable with DataLink * information The VOTABLE must contain only Datalink info! ????? or? * * @throws IOException */ public DataLinkParams(String dataLinksrc) throws IOException { id_source = null; request = null; accessURL = null; contentType = null; service = new ArrayList<DataLinkService>(); DataLinkService thisService = new DataLinkService(); URL dataLinkURL = new URL(dataLinksrc); DataSource datsrc = new URLDataSource(dataLinkURL); StarTable starTable = new VOTableBuilder().makeStarTable(datsrc, true, StoragePolicy.getDefaultPolicy()); int ncol = starTable.getColumnCount(); for (int k = 0; k < ncol; k++) { ColumnInfo colInfo = starTable.getColumnInfo(k); // String utype = colInfo.getUtype(); String name = colInfo.getName(); if (name != null) thisService.addParam(name, (String) starTable.getCell(0, k)); // if ( utype != null ) { // utype = utype.toLowerCase(); // if ( utype.endsWith( "datalink.accessurl" ) ) { // thisService.addParam("accessURL", (String) starTable.getCell(0, k)); // } // if ( utype.endsWith( "datalink.contenttype" ) ) { // thisService.addParam("contentType", (String) starTable.getCell(0, k)); // } } service.add(thisService); }
/** * Constructor. * * @param inTable saved table as read */ public CodecTable(StarTable inTable) { /* Sort out table parameters. */ codecParamMap_ = new HashMap<String, DescribedValue>(); List<DescribedValue> dataParamList = new ArrayList<DescribedValue>(); for (Iterator it = inTable.getParameters().iterator(); it.hasNext(); ) { DescribedValue param = (DescribedValue) it.next(); String utype = param.getInfo().getUtype(); if (isCodecUtype(utype)) { codecParamMap_.put(utype, param); } else { dataParamList.add(param); } } /* Sort out table columns. */ codecIcolMap_ = new HashMap<String, Integer>(); IntList dataIcolList = new IntList(); for (int icol = 0; icol < inTable.getColumnCount(); icol++) { ColumnInfo info = inTable.getColumnInfo(icol); String utype = info.getUtype(); if (isCodecUtype(utype)) { codecIcolMap_.put(utype, icol); } else { dataIcolList.add(icol); } } int[] dataColMap = dataIcolList.toIntArray(); /* Construct a table containing only the data items. */ dataTable_ = new MetaCopyStarTable(new ColumnPermutedStarTable(inTable, dataColMap, true)); dataTable_.getParameters().clear(); dataTable_.getParameters().addAll(dataParamList); }
public ConeQueryRowSequence createQuerySequence(StarTable table) throws IOException { assert rowMap_ == null || rowMap_.length == table.getRowCount(); final RowSequence rseq = table.getRowSequence(); return new ConeQueryRowSequence() { long irow_ = -1; public boolean next() throws IOException { if (matchWorker_ != null && matchWorker_.cancelled_) { throw new IOException("Cancelled"); } boolean retval = rseq.next(); if (matchWorker_ != null && matchWorker_.cancelled_) { throw new IOException("Cancelled"); } if (retval) { irow_++; if (matchWorker_ != null) { matchWorker_.setInputRow((int) irow_); } } return retval; } public Object getCell(int icol) throws IOException { return rseq.getCell(icol); } public Object[] getRow() throws IOException { return rseq.getRow(); } public void close() throws IOException { rseq.close(); } public double getRa() throws IOException { return Math.toDegrees(getDoubleValue(raData_)); } public double getDec() throws IOException { return Math.toDegrees(getDoubleValue(decData_)); } public double getRadius() throws IOException { return Math.toDegrees(getDoubleValue(srData_)); } private double getDoubleValue(ColumnData cdata) throws IOException { if (cdata != null) { long jrow = rowMap_ == null ? irow_ : rowMap_[(int) irow_]; Object value = cdata.readValue(jrow); return value instanceof Number ? ((Number) value).doubleValue() : Double.NaN; } else { return Double.NaN; } } }; }
/** * Sets the table value of this parameter directly. * * @param table */ public void setValueFromTable(StarTable table) { table_ = table; String name = table.getName(); if (name == null) { name = "unnamed table"; } setStringValue(name); setGotValue(true); }
/** * Loads a StarTable into TOPCAT. Must be called from the event dispatch thread. * * @param table table to load * @param sender sender ID * @param key identifier for the loaded table */ private void loadTable(StarTable table, URI sender, String key) { String name = table.getName(); if (name == null || name.trim().length() == 0) { name = sender.toString(); } TopcatModel tcModel = controlWindow_.addTable(table, name, true); if (key != null && key.trim().length() > 0) { idMap_.put(key, new TableWithRows(tcModel, null)); } }
public void processResult(StarTable streamTable) throws IOException { /* Blocks until all results are in. */ StarTable randomTable = policy_.copyTable(streamTable); long nrow = randomTable.getRowCount(); /* Either note that there are no results. */ if (nrow == 0) { schedule( new Runnable() { public void run() { JOptionPane.showMessageDialog( parent_, "No matches were found", "Empty Match", JOptionPane.ERROR_MESSAGE); } }); } /* Or invoke the method that does the work. */ else { processRandomResult(randomTable); } }
public void writeData(DataOutput strm) throws IOException { /* Work out the length of each row in bytes. */ int rowBytes = 0; int ncol = table.getColumnCount(); for (int icol = 0; icol < ncol; icol++) { ColumnWriter writer = colWriters[icol]; if (writer != null) { rowBytes += writer.getLength(); } } /* Write the data cells, delegating the item in each column to * the writer that knows how to handle it. */ long nWritten = 0L; RowSequence rseq = table.getRowSequence(); try { while (rseq.next()) { Object[] row = rseq.getRow(); for (int icol = 0; icol < ncol; icol++) { ColumnWriter writer = colWriters[icol]; if (writer != null) { writer.writeValue(strm, row[icol]); } } nWritten += rowBytes; } } finally { rseq.close(); } /* Write padding. */ int extra = (int) (nWritten % (long) 2880); if (extra > 0) { strm.write(new byte[2880 - extra]); } }
/** * Returns a table which is the same as the input table, but with a zero-based index column as the * first column. * * @param inTable input table * @return output table */ private static StarTable prependIndex(StarTable inTable) { final long nrow = inTable.getRowCount(); ColumnStarTable indexTable = new ColumnStarTable(inTable) { public long getRowCount() { return nrow; } }; indexTable.addColumn( new ColumnData(INDEX_INFO) { public Object readValue(long irow) { return new Integer((int) irow); } }); return new JoinStarTable(new StarTable[] {indexTable, inTable}); }
/** * Generates an array of some kind of data item (probably an integer type or possibly integer * array) suitable for placing in a table column. This array has the same number of elements as * the table has rows, and encodes the content of the supplied subsets. * * @param table input table * @param subsets subsets applying to table * @return nrow-element array */ private Object createFlagsArray(StarTable table, RowSubset[] subsets) { int nrow = Tables.checkedLongToInt(table.getRowCount()); int nset = subsets.length; if (nset < 16) { short[] flags = new short[nrow]; for (int irow = 0; irow < nrow; irow++) { int flag = 0; for (int iset = nset - 1; iset >= 0; iset--) { flag <<= 1; if (subsets[iset].isIncluded(irow)) { flag = flag | 1; } } flags[irow] = (short) flag; } return flags; } else if (nset < 32) { int[] flags = new int[nrow]; for (int irow = 0; irow < nrow; irow++) { int flag = 0; for (int iset = nset - 1; iset >= 0; iset--) { flag <<= 1; if (subsets[iset].isIncluded(irow)) { flag = flag | 1; } } flags[irow] = flag; } return flags; } else if (nset < 64) { long[] flags = new long[nrow]; for (int irow = 0; irow < nrow; irow++) { long flag = 0L; for (int iset = nset - 1; iset >= 0; iset--) { flag <<= 1; if (subsets[iset].isIncluded(irow)) { flag = flag | 1L; } } flags[irow] = flag; } return flags; } else { logger_.warning("More than 64 subsets??"); return null; } }
/** * Generates a RowSubset from a column like one generated by a call to {@link #createFlagsArray}. * * @param name subset name * @param table input table * @param icol index of column containing flag data * @param iflag index of flag within column * @return iflag'th subset derived from column icol in table */ private RowSubset createRowSubset(String name, final StarTable table, final int icol, int iflag) { ColumnInfo info = table.getColumnInfo(icol); Class clazz = info.getContentClass(); if (clazz == Short.class) { final short mask = (short) (1 << iflag); return new RowSubset(name) { public boolean isIncluded(long lrow) { try { return (((Number) table.getCell(lrow, icol)).shortValue() & mask) != 0; } catch (IOException e) { return false; } } }; } else if (clazz == Integer.class) { final int mask = 1 << iflag; return new RowSubset(name) { public boolean isIncluded(long lrow) { try { return (((Number) table.getCell(lrow, icol)).intValue() & mask) != 0; } catch (IOException e) { return false; } } }; } else if (clazz == Long.class) { final long mask = 1L << iflag; return new RowSubset(name) { public boolean isIncluded(long lrow) { try { return (((Number) table.getCell(lrow, icol)).longValue() & mask) != 0; } catch (IOException e) { return false; } } }; } else { logger_.warning("Can't decode subsets column"); return null; } }
/** * @param ra - in degrees * @param dec - in degrees * @param angularWidthAlongRAAxis - width along RA axis * @param angularWidthAlongDecAxis - width along DEC axis * @param otherConstraints - map of UCDKey -> Value. Only images whose column UCDs match the * values are selected * @return array of fits image urls * @throws Exception - */ public String[] fetchFitsImages( double ra, double dec, double angularWidthAlongRAAxis, double angularWidthAlongDecAxis, Map<String, Object> otherConstraints) throws MalformedURLException, SAXException, IOException, NoValidResultsResourceFoundException, SiaQueryFailedException { // TODO: Need to take a call on the otherConstraints argument String modurl = url + "&FORMAT=image/fits"; modurl += "&POS=" + ra + "," + dec; modurl += "&SIZE=" + angularWidthAlongRAAxis + "," + angularWidthAlongDecAxis; URL siaUrl = new URL(modurl); logger.info("Connecting to SIA URL: " + siaUrl); String interestedImageFormat = "image/fits"; ArrayList<String> imageUrls = new ArrayList<String>(); VOElement votable = new VOElementFactory().makeVOElement(siaUrl); NodeList resources = votable.getElementsByTagName("RESOURCE"); // check for a "results" resource with of sia votable resu int resInd = 0; for (; resInd < resources.getLength(); resInd++) { VOElement resource = (VOElement) resources.item(resInd); if (SIAP_RESOURCE_TYPE_VALUE_RESULTS.equals(resource.getAttribute("type"))) { break; } } if (resInd == resources.getLength()) { throw new NoValidResultsResourceFoundException(); } else { String queryStatus = null; String queryStatusDescription = null; // check query status VOElement resource = (VOElement) resources.item(resInd); NodeList infos = resource.getElementsByTagName("INFO"); for (int infoInd = 0; infoInd < infos.getLength(); infoInd++) { VOElement info = (VOElement) infos.item(infoInd); String name = info.getAttribute("name"); if (name.equals(QUERY_STATUS)) { queryStatus = info.getAttribute("value"); queryStatusDescription = info.getNodeValue(); } } // if query successful.equalsIgnoreCase() if (!queryStatus.equals(QUERY_STATUS_VALUE_OK)) { throw new SiaQueryFailedException(queryStatusDescription); } // handle the table VOElement[] tables = resource.getChildrenByName("TABLE"); if (tables.length > 0) { // take the first table and look for URLs in it. TableElement tableElement = (TableElement) tables[0]; // create star-table StarTable table = new VOStarTable(tableElement); // ideally its mandatory to have RA_UCD, DEC_UCD, NAXES_UCD, // NAXIS_UCD, FORMAT_UCD, SCALE_UCD in each row but we will not // check for those as of now. int formatColIndex = -1; int urlColIndex = -1; int otherConstraintsSize = (otherConstraints != null) ? otherConstraints.size() : 0; HashMap<String, Integer> otherConstraintsIndices = new HashMap<String, Integer>(); for (int colInd = 0; colInd < table.getColumnCount(); colInd++) { ColumnInfo colInfo = table.getColumnInfo(colInd); if (colInfo.getUCD().equalsIgnoreCase(FORMAT_UCD)) { formatColIndex = colInd; } else if (colInfo.getUCD().equalsIgnoreCase(ACCESS_REF_UCD)) { urlColIndex = colInd; } if (otherConstraintsSize > 0) { Iterator<String> keyIte = otherConstraints.keySet().iterator(); while (keyIte.hasNext()) { String key = keyIte.next(); if (key.equalsIgnoreCase(colInfo.getUCD())) { otherConstraintsIndices.put(key, colInd); } } } } for (int rowInd = 0; rowInd < table.getRowCount(); rowInd++) { Object[] cells = table.getRow(rowInd); // looking for only FITS images or JPG images .. .. if (interestedImageFormat.equalsIgnoreCase((String) cells[formatColIndex])) { Iterator<String> keyIte = otherConstraintsIndices.keySet().iterator(); boolean allConstraintsPassed = true; while (keyIte.hasNext()) { String key = keyIte.next(); int keyInd = otherConstraintsIndices.get(key); if (!cells[keyInd].equals(otherConstraints.get(key))) { allConstraintsPassed = false; break; } } if (allConstraintsPassed) { imageUrls.add((String) cells[urlColIndex]); } } } } return imageUrls.toArray(new String[] {}); } }
public void run() { /* Initialise progress GUI. */ final int nrow = (int) inTable_.getRowCount(); schedule( new Runnable() { public void run() { progBar_.setMinimum(0); progBar_.setMaximum(nrow); } }); setOutputRow(0); /* Acquire the table from the matcher in such a way that * when each row arrives the progress GUI is updated. */ matcher_.setStreamOutput(true); try { ConeMatcher.ConeWorker coneWorker = matcher_.createConeWorker(); coneThread_ = new Thread(coneWorker, "Cone worker"); coneThread_.setDaemon(true); coneThread_.start(); StarTable streamTable = coneWorker.getTable(); StarTable progressTable = new WrapperStarTable(streamTable) { public RowSequence getRowSequence() throws IOException { return new WrapperRowSequence(super.getRowSequence()) { long irow_ = -1; public boolean next() throws IOException { if (cancelled_) { throw new IOException("Cancelled"); } boolean retval = super.next(); if (cancelled_) { throw new IOException("Cancelled"); } if (retval) { irow_++; setOutputRow((int) irow_); } return retval; } }; } }; /* And pass the table to the appropriate result handler. * The row data has not been acquired yet, it will be pulled * by the action of the processResult call. */ resultHandler_.processResult(progressTable); } /* In case of error in result acquisition or processing, * inform the user. */ catch (final Exception e) { schedule( new Runnable() { public void run() { ErrorDialog.showError( DalMultiPanel.this, "Multi-" + service_.getName() + " Error", e); } }); } catch (final OutOfMemoryError e) { schedule( new Runnable() { public void run() { TopcatUtils.memoryError(e); } }); } /* In any case, deinstall this worker thread. No further actions * on its behalf will now affect the GUI (important, since another * worker thread might take over). */ finally { done_ = true; schedule( new Runnable() { public void run() { setActive(null); } }); } }
/** * Turns a TopcatModel into a StarTable, ready for serialization. * * @param tcModel model * @return table */ public StarTable encode(TopcatModel tcModel) { /* Prepare table data and metadata for use and adjustment. */ final StarTable dataModel = tcModel.getDataModel(); List<DescribedValue> paramList = new ArrayList<DescribedValue>(); long nrow = dataModel.getRowCount(); ColumnStarTable extraTable = ColumnStarTable.makeTableWithRows(nrow); /* Mark as serialized TopcatModel. */ paramList.add(new DescribedValue(IS_TCMODEL_INFO, Boolean.TRUE)); paramList.add(new DescribedValue(VERSION_INFO, TopcatUtils.getVersion())); /* Record label. */ paramList.add(new DescribedValue(LABEL_INFO, tcModel.getLabel())); /* Record column sequences. */ ColumnList colList = tcModel.getColumnList(); int nCol = colList.size(); int[] icols = new int[nCol]; boolean[] activs = new boolean[nCol]; for (int jc = 0; jc < nCol; jc++) { icols[jc] = colList.getColumn(jc).getModelIndex(); activs[jc] = colList.isActive(jc); } paramList.add(new DescribedValue(COLS_INDEX_INFO, icols)); paramList.add(new DescribedValue(COLS_VISIBLE_INFO, activs)); /* Record whether to broadcast rows. */ paramList.add(new DescribedValue(SEND_ROWS_INFO, tcModel.getRowSendModel().isSelected())); /* Record sort order. */ SortOrder sortOrder = tcModel.getSelectedSort(); TableColumn sortCol = sortOrder == null ? null : sortOrder.getColumn(); if (sortCol != null) { int icolSort = tcModel.getColumnList().indexOf(sortCol); if (icolSort >= 0) { boolean sense = tcModel.getSortSenseModel().isSelected(); paramList.add(new DescribedValue(SORT_COLUMN_INFO, new Integer(icolSort))); paramList.add(new DescribedValue(SORT_SENSE_INFO, Boolean.valueOf(sense))); } } /* Store row subset flags in a new column. */ List<RowSubset> subsetList = new ArrayList<RowSubset>(tcModel.getSubsets()); boolean hadAll = subsetList.remove(RowSubset.ALL); assert hadAll; RowSubset[] subsets = subsetList.toArray(new RowSubset[0]); if (subsets.length > 0) { String[] subsetNames = new String[subsets.length]; for (int is = 0; is < subsets.length; is++) { subsetNames[is] = subsets[is].getName(); } paramList.add(new DescribedValue(SUBSET_NAMES_INFO, subsetNames)); Object flagsArray = createFlagsArray(dataModel, subsets); if (flagsArray != null) { ColumnData flagsCol = ArrayColumn.makeColumn(SUBSET_FLAGS_INFO.getName(), flagsArray); ColumnInfo info = new ColumnInfo(SUBSET_FLAGS_INFO); info.setContentClass(flagsCol.getColumnInfo().getContentClass()); flagsCol.setColumnInfo(info); extraTable.addColumn(flagsCol); } } /* Record current subset. */ int iset = subsetList.indexOf(tcModel.getSelectedSubset()); if (iset >= 0) { paramList.add(new DescribedValue(CURRENT_SUBSET_INFO, new Integer(iset))); } /* Copy parameters from the input table. * Be paranoid about possible name clashes. */ for (Iterator it = dataModel.getParameters().iterator(); it.hasNext(); ) { Object item = it.next(); if (item instanceof DescribedValue) { DescribedValue dval = (DescribedValue) item; String name = dval.getInfo().getName(); String utype = dval.getInfo().getUtype(); if (!isCodecUtype(utype)) { paramList.add(dval); } } } /* Prepare the output table object. */ List<StarTable> joinList = new ArrayList<StarTable>(); joinList.add(dataModel); if (extraTable.getColumnCount() > 0) { joinList.add(extraTable); } StarTable[] joins = joinList.toArray(new StarTable[0]); StarTable outTable = new MetaCopyStarTable(new JoinStarTable(joinList.toArray(new StarTable[0]))); outTable.setName(dataModel.getName()); /* Set the parameters. */ outTable.getParameters().clear(); outTable.getParameters().addAll(paramList); /* Return the result. */ return outTable; }
/** * Configures this serializer for use with a given table and column writer factory. Should be * called before this object is ready for use; in a constructor would be a good place. Calls * {@link #createColumnWriter}. * * @param table table to be written */ final void init(StarTable table) throws IOException { if (this.table != null) { throw new IllegalStateException("Table already initialised"); } this.table = table; /* Get table dimensions (though we may need to calculate the row * count directly later. */ int ncol = table.getColumnCount(); long nrow = table.getRowCount(); /* Store column infos. */ colInfos = Tables.getColumnInfos(table); /* Work out column shapes, and check if any are unknown (variable * last dimension). */ boolean hasVarShapes = false; boolean checkForNullableInts = false; int[][] shapes = new int[ncol][]; int[] maxChars = new int[ncol]; int[] maxElements = new int[ncol]; long[] totalElements = new long[ncol]; boolean[] useCols = new boolean[ncol]; boolean[] varShapes = new boolean[ncol]; boolean[] varChars = new boolean[ncol]; boolean[] varElementChars = new boolean[ncol]; boolean[] mayHaveNullableInts = new boolean[ncol]; Arrays.fill(useCols, true); boolean[] hasNulls = new boolean[ncol]; for (int icol = 0; icol < ncol; icol++) { ColumnInfo colinfo = colInfos[icol]; Class clazz = colinfo.getContentClass(); if (clazz.isArray()) { shapes[icol] = (int[]) colinfo.getShape().clone(); int[] shape = shapes[icol]; if (shape[shape.length - 1] < 0) { varShapes[icol] = true; hasVarShapes = true; } else { int nel = shape.length > 0 ? 1 : 0; for (int id = 0; id < shape.length; id++) { nel *= shape[id]; } assert nel >= 0; maxElements[icol] = nel; } if (clazz.getComponentType().equals(String.class)) { maxChars[icol] = colinfo.getElementSize(); if (maxChars[icol] <= 0) { varElementChars[icol] = true; hasVarShapes = true; } } } else if (clazz.equals(String.class)) { maxChars[icol] = colinfo.getElementSize(); if (maxChars[icol] <= 0) { varChars[icol] = true; hasVarShapes = true; } } else if (colinfo.isNullable() && (clazz == Byte.class || clazz == Short.class || clazz == Integer.class || clazz == Long.class)) { mayHaveNullableInts[icol] = true; /* Only set the flag which forces a first pass if we need * to work out whether nulls actually exist. If the * aux datum giving a null value exists we will use it in * any case, so finding out whether there are in fact null * values by scanning the data is not necessary. */ if (colinfo.getAuxDatumValue(Tables.NULL_VALUE_INFO, Number.class) != null) { hasNulls[icol] = true; } else { checkForNullableInts = true; } } } /* If necessary, make a first pass through the table data to * find out the maximum size of variable length fields and the length * of the table. */ if (hasVarShapes || checkForNullableInts || nrow < 0) { StringBuffer sbuf = new StringBuffer("First pass needed: "); if (hasVarShapes) { sbuf.append("(variable array shapes) "); } if (checkForNullableInts) { sbuf.append("(nullable ints) "); } if (nrow < 0) { sbuf.append("(unknown row count) "); } logger.config(sbuf.toString()); nrow = 0L; /* Get the maximum dimensions. */ RowSequence rseq = table.getRowSequence(); try { while (rseq.next()) { nrow++; for (int icol = 0; icol < ncol; icol++) { if (useCols[icol] && (varShapes[icol] || varChars[icol] || varElementChars[icol] || (mayHaveNullableInts[icol] && !hasNulls[icol]))) { Object cell = rseq.getCell(icol); if (cell == null) { if (mayHaveNullableInts[icol]) { hasNulls[icol] = true; } } else { if (varChars[icol]) { int leng = ((String) cell).length(); maxChars[icol] = Math.max(maxChars[icol], leng); } else if (varElementChars[icol]) { String[] svals = (String[]) cell; for (int i = 0; i < svals.length; i++) { maxChars[icol] = Math.max(maxChars[icol], svals[i].length()); } } if (varShapes[icol]) { int nel = Array.getLength(cell); maxElements[icol] = Math.max(maxElements[icol], nel); totalElements[icol] += nel; } } } } } } finally { rseq.close(); } /* In the case of variable string lengths and no non-null data * in any of the cells, maxChars could still be set negative. * Fix that here. */ for (int icol = 0; icol < ncol; icol++) { if (maxChars[icol] < 0) { maxChars[icol] = 0; } } /* Furthermore, zero length strings are probably a bad idea * for FITS output. Make sure that all output strings have * a length of at least 1. */ for (int icol = 0; icol < ncol; icol++) { if (maxChars[icol] == 0) { maxChars[icol] = 1; } } /* Work out the actual shapes for columns which have variable ones, * based on the shapes that we encountered in the rows. */ if (hasVarShapes) { for (int icol = 0; icol < ncol; icol++) { if (useCols[icol]) { if (varShapes[icol]) { int[] shape = shapes[icol]; int ndim = shape.length; assert shape[ndim - 1] <= 0; int nel = 1; for (int i = 0; i < ndim - 1; i++) { nel *= shape[i]; } shape[ndim - 1] = Math.max(1, (maxElements[icol] + nel - 1) / nel); } } } } } /* Store the row count, which we must have got by now. */ assert nrow >= 0; rowCount = nrow; /* We now have all the information we need about the table. * Construct and store a custom writer for each column which * knows about the characteristics of the column and how to * write values to the stream. For columns which can't be * written in FITS format store a null in the writers array * and log a message. */ colWriters = new ColumnWriter[ncol]; int rbytes = 0; for (int icol = 0; icol < ncol; icol++) { if (useCols[icol]) { ColumnInfo cinfo = colInfos[icol]; ColumnWriter writer = createColumnWriter( cinfo, shapes[icol], varShapes[icol], maxChars[icol], maxElements[icol], totalElements[icol], mayHaveNullableInts[icol] && hasNulls[icol]); if (writer == null) { logger.warning( "Ignoring column " + cinfo.getName() + " - don't know how to write to FITS"); } colWriters[icol] = writer; } } }
public Header getHeader() throws HeaderCardException { /* Work out the dimensions in columns and bytes of the table. */ int rowLength = 0; int nUseCol = 0; int ncol = table.getColumnCount(); for (int icol = 0; icol < ncol; icol++) { ColumnWriter writer = colWriters[icol]; if (writer != null) { nUseCol++; rowLength += writer.getLength(); } } /* Prepare a FITS header block. */ Header hdr = new Header(); /* Add HDU layout metadata. */ hdr.addValue("XTENSION", "BINTABLE", "binary table extension"); hdr.addValue("BITPIX", 8, "8-bit bytes"); hdr.addValue("NAXIS", 2, "2-dimensional table"); hdr.addValue("NAXIS1", rowLength, "width of table in bytes"); hdr.addValue("NAXIS2", rowCount, "number of rows in table"); hdr.addValue("PCOUNT", 0, "size of special data area"); hdr.addValue("GCOUNT", 1, "one data group"); hdr.addValue("TFIELDS", nUseCol, "number of columns"); /* Add EXTNAME record containing table name. */ String tname = table.getName(); if (tname != null && tname.trim().length() > 0) { FitsConstants.addTrimmedValue(hdr, "EXTNAME", tname, "table name"); } /* Add HDU metadata describing columns. */ int jcol = 0; for (int icol = 0; icol < ncol; icol++) { ColumnWriter colwriter = colWriters[icol]; if (colwriter != null) { jcol++; String forcol = " for column " + jcol; ColumnInfo colinfo = colInfos[icol]; /* Name. */ String name = colinfo.getName(); if (name != null && name.trim().length() > 0) { FitsConstants.addTrimmedValue(hdr, "TTYPE" + jcol, name, "label" + forcol); } /* Format. */ String form = colwriter.getFormat(); hdr.addValue("TFORM" + jcol, form, "format" + forcol); /* Units. */ String unit = colinfo.getUnitString(); if (unit != null && unit.trim().length() > 0) { FitsConstants.addTrimmedValue(hdr, "TUNIT" + jcol, unit, "units" + forcol); } /* Blank. */ Number bad = colwriter.getBadNumber(); if (bad != null) { hdr.addValue("TNULL" + jcol, bad.longValue(), "blank value" + forcol); } /* Shape. */ int[] dims = colwriter.getDims(); if (dims != null && dims.length > 1) { StringBuffer sbuf = new StringBuffer(); for (int i = 0; i < dims.length; i++) { sbuf.append(i == 0 ? '(' : ','); sbuf.append(dims[i]); } sbuf.append(')'); hdr.addValue("TDIM" + jcol, sbuf.toString(), "dimensions" + forcol); } /* Scaling. */ double zero = colwriter.getZero(); double scale = colwriter.getScale(); if (zero != 0.0) { hdr.addValue("TZERO" + jcol, zero, "base" + forcol); } if (scale != 1.0) { hdr.addValue("TSCALE" + jcol, scale, "factor" + forcol); } /* Comment (non-standard). */ String comm = colinfo.getDescription(); if (comm != null && comm.trim().length() > 0) { try { hdr.addValue("TCOMM" + jcol, comm, null); } catch (HeaderCardException e) { // never mind. } } /* UCD (non-standard). */ String ucd = colinfo.getUCD(); if (ucd != null && ucd.trim().length() > 0 && ucd.length() < 68) { try { hdr.addValue("TUCD" + jcol, ucd, null); } catch (HeaderCardException e) { // never mind. } } /* Utype (non-standard). */ String utype = colinfo.getUtype(); if (utype != null && utype.trim().length() > 0 && utype.trim().length() < 68) { try { hdr.addValue("TUTYP" + jcol, utype, null); } catch (HeaderCardException e) { // never mind. } } } } return hdr; }